English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
بما أن من لا يعرف من هو الأول في تنفيذ العمليات ليس معروفًا، يعتمد ذلك على خوارزمية توجيه العمليات النواة، وهي معقدة. لذا، من الممكن أن يصل أكثر من عملية في نفس الوقت إلى الذاكرة المشتركة، مما يؤدي إلى أخطاء غير متوقعة. اسم السيمافورس غير مفهوم، لكن إذا نظرنا إلى معناه الأصلي باللغة الإنجليزية، فإنه سهل الفهم.
semaphore إنجليزي [ˈseməfɔ:(r)] vt. إرسال إشارة، رفع الراية;
مثل دور القائد.
دعنا نرى استخدام السيمافورس في الشيفرة الوهمية التالية.
1. إنشاء معرف فريد للسيمافورس
$ftok = ftok(__FILE__, 'a');
2. إنشاء معرف مصدر السيمافورس
$sem_resouce_id = sem_get($ftok);
3. استقبال السيمافورس
sem_acqure($sem_resource_id);
4. إطلاق السيمافورس
sem_release($sem_resource_id);
5. إزالة السيمافورس
sem_remove($sem_resource_id);
لنأخذ مثالاً غير لائقًا لفهم استخدام السيمافورس في حياتنا اليومية. بعد الفهم يمكن تطبيق ذلك في مجال البرمجة.
في الشركة هناك مرحاض واحد فقط. عند استخدام المرحاض، يجب الحصول على قفل (السيمافورس) ليعني أن المرحاض مستخدم حاليًا. الشيفرة كالتالي:
sem_acqure($sem_resource_id);
بعد أن يستخدم الموظف المرحاض، يجب فتح القفل، إطلاق القفل (السيمافورس)، مما يعني أن يمكن السماح للآخرين باستخدامه. الشيفرة كالتالي:
sem_release($sem_resource_id);
من خلال قفل بسيط، يمكننا معرفة ما إذا كان المرحاض (الذاكرة المشتركة) قابلاً الاستخدام. هذا المثال غير لائق، لكنه يوضح المشكلة. هذا المقال هو أيضًا مقال به رائحة، من الصعب جدًا。。。。هناك مثال على الشيفرة:
<?php //إنشاء منطقة ذاكرة مشتركة $shm_key = ftok(__FILE__, 'a'); $shm_id = shm_attach($shm_key, 1024, 0755); //var_dump($shm_id);die(); resource(4) of type (sysvshm) const SHARE_KEY = 1; $child_list = []; //إضافة signal resource (5) $sem_id = ftok(__FILE__, 'b'); $signal = sem_get($sem_id); //مورد signal (5) من نوع (sysvsem) لـ $i = 0; $i < 3; $i++) { $pid = pcntl_fork(); exit("Fork fail!".PHP_EOL); elseif ($pid == 0) { } //الحصول على إشارة الديناميكية sem_acquire($signal); if (shm_has_var($shm_id,SHARE_KEY)) { $count = shm_get_var($shm_id, SHARE_KEY); $count++; //تقليد معالجة الأعمال $sec = rand(1, 3); sleep($sec); shm_put_var($shm_id, SHARE_KEY, $count); } $count = 0; $sec = rand(1, 3); sleep($sec); shm_put_var($shm_id, SHARE_KEY, $count); } echo "child process: ".getmypid()." is writing! now count is: $count ".PHP_EOL; //إطلاق إشارة الديناميكية sem_release($signal); exit("child process".getmypid()."end".PHP_EOL); } $child_list[] = $pid; } } while (count($child_list) > 0) { foreach ($child_list as $key => $pid) { $status = pcntl_waitpid($pid, $status); if ($status > 0 || $status == -1) { unset($child_list[$key]); } } sleep(1); } $count = shm_get_var($shm_id, SHARE_KEY); echo " $count ".PHP_EOL; //تدمير إشارة الديناميكية sem_remove($signal); shm_remove($shm_id); shm_detach($shm_id);