عملية الزومبي
في أنظمة تشغيل يونكس وما يشابهها ، تُعرف العملية المُعلقة أو العملية المُعطلة بأنها عملية انتهت من التنفيذ (عبر استدعاء النظام ) ولكنها لا تزال موجودة في جدول العمليات ، أي أنها في حالة "إنهاء ". يحدث هذا مع العمليات الفرعية ، حيث لا يزال هذا الإدخال ضروريًا لتمكين العملية الأصلية من قراءة حالة خروج العملية الفرعية . بمجرد قراءة حالة الخروج عبر استدعاء النظام ، يُزال إدخال العملية المُعطلة من جدول العمليات، ويُقال إنها "حُصدت". تصبح العملية الفرعية مُعطلة في البداية، ثم تُزال من جدول الموارد. في ظل التشغيل العادي للنظام، تنتظر العملية الأصلية العمليات المُعطلة فورًا، ثم يحصدها النظام. عادةً ما تُمثل العمليات التي تبقى مُعطلة لفترة طويلة خطأً، وقد تُسبب تسربًا للموارد . بشكل عام، المورد الوحيد الذي تشغله في النواة هو إدخالها في جدول العمليات، أي مُعرّف العملية. مع ذلك، يُمكن للعمليات المُعطلة أيضًا أن تُبقي المخازن المؤقتة مفتوحة، مما يُؤدي إلى استهلاك الذاكرة. قد تحتفظ العمليات المتوقفة بمقابض لمعرفات الملفات، مما يمنع نظام الملفات من الوصول إلى مساحة تخزين تلك الملفات. يمكن ملاحظة هذا التأثير من خلال الفرق بين `<file>` و` <file> `. فبينما قد يُظهر `<file>` مساحة كبيرة من القرص الحر، سيُظهر `<file>` قسمًا كاملاً. إذا لم تُحذف العمليات المتوقفة، فقد يؤدي ذلك إلى امتلاء قسم الجذر وتعطل النظام.exitwaitdudfdudf
يُشتق مصطلح " العملية الزومبي" من التعريف الشائع للزومبي - وهو شخص غير ميت . في استعارة المصطلح، تكون العملية الفرعية قد " ماتت " ولكن لم يتم " حصدها " بعد. على عكس العمليات العادية، لا يؤثر الأمر على العملية الزومبي. kill
لا ينبغي الخلط بين العمليات الزومبي والعمليات اليتيمة ، وهي عملية لا تزال قيد التنفيذ، ولكن العملية الأصلية قد توقفت. عندما تتوقف العملية الأصلية، تتبنى العملية اليتيمة العملية الفرعية init. وعندما تتوقف العمليات اليتيمة، فإنها لا تبقى كعمليات زومبي؛ بل يتم waitاستكمالها بواسطة العملية الأصلية init.
ملخص
عند انتهاء عملية ما exit، يتم تحرير جميع الذاكرة والموارد المرتبطة بها لتتمكن العمليات الأخرى من استخدامها. مع ذلك، يبقى سجل العملية في جدول العمليات. يمكن للعملية الأصلية قراءة حالة خروج العملية الفرعية بتنفيذ waitاستدعاء النظام ، وعندها تُزال العملية المعلقة. waitقد يُنفذ الاستدعاء في التعليمات البرمجية التسلسلية، ولكنه يُنفذ عادةً في معالج إشارة SIGCHLD ، التي تتلقاها العملية الأصلية عند انتهاء أي عملية فرعية .
بعد إزالة العملية الزومبي، يمكن إعادة استخدام مُعرّف العملية (PID) الخاص بها وإدخالها في جدول العمليات. مع ذلك، إذا لم تستدعِ العملية الأصلية الدالة المناسبة wait، فستبقى العملية الزومبي في جدول العمليات، مما يُسبب تسريبًا للموارد . في بعض الحالات، قد يكون هذا مرغوبًا - حيث ترغب العملية الأصلية في الاستمرار في الاحتفاظ بهذا المورد - على سبيل المثال، إذا أنشأت العملية الأصلية عملية فرعية أخرى، فإنها تضمن عدم تخصيص نفس مُعرّف العملية لها. في أنظمة يونكس الحديثة (التي تتوافق مع مواصفات SUSv3 في هذا الصدد)، تنطبق الحالة الخاصة التالية: إذا تجاهلت العملية الأصلية إشارة SIGCHLD صراحةً عن طريق ضبط مُعالجها على SIG_IGN(بدلاً من تجاهل الإشارة افتراضيًا) أو إذا تم SA_NOCLDWAITتعيين العلامة، فسيتم تجاهل جميع معلومات حالة خروج العملية الفرعية ولن تبقى أي عمليات زومبي. [ 1 ]
يمكن تحديد العمليات الزومبية في مخرجات psأمر يونكس من خلال وجود علامة " Z" في عمود "STAT". [ 2 ] تشير العمليات الزومبية التي تستمر لفترة طويلة عادةً إلى وجود خلل في البرنامج الرئيسي، أو مجرد قرار غير معتاد بعدم حذف العمليات الفرعية (انظر المثال). إذا توقف البرنامج الرئيسي عن العمل، فإن العمليات الزومبية تشير عادةً إلى وجود خلل في نظام التشغيل. وكما هو الحال مع تسريبات الموارد الأخرى، فإن وجود عدد قليل من العمليات الزومبية ليس مدعاة للقلق في حد ذاته، ولكنه قد يشير إلى مشكلة قد تتفاقم مع زيادة الأحمال. نظرًا لعدم تخصيص ذاكرة للعمليات الزومبية - حيث يقتصر استخدام ذاكرة النظام على إدخال جدول العمليات نفسه - فإن الشاغل الرئيسي مع وجود العديد من العمليات الزومبية ليس نفاد الذاكرة ، بل نفاد إدخالات جدول العمليات، وتحديدًا أرقام تعريف العمليات. ومع ذلك، يمكن للعمليات الزومبية الاحتفاظ بمخازن مؤقتة مفتوحة مرتبطة بمؤشرات الملفات، مما يؤدي إلى استهلاك الذاكرة من قبل العملية الزومبية. كما يمكن للعمليات الزومبية الاحتفاظ بمؤشر ملف لملف تم حذفه. يمنع هذا نظام الملفات من استعادة عقد i-nodes للملف المحذوف. لذا، لن يحسب أمر عرض استخدام القرص الملفات المحذوفة التي لا يمكن إعادة استخدام مساحتها بسبب وجود ملف زومبي يحتفظ بوصف الملف.
لإزالة العمليات المعلقة من النظام، يمكن إرسال إشارةkill SIGCHLD إلى العملية الأصلية يدويًا باستخدام الأمر. إذا استمرت العملية الأصلية في رفض إزالة العملية المعلقة، وكان من المناسب إنهاء العملية الأصلية، فيمكن حذف العملية الأصلية. عندما تفقد عملية ما عمليتها الأصلية، initتصبح العملية الأصلية هي العملية الأصلية الجديدة. initيقوم النظام بتنفيذ استدعاء النظام بشكل دوري waitلإزالة أي عمليات معلقة يكون لها initالعملية الأصلية.
مثال
قد يؤدي انتظار عمليات فرعية محددة بترتيب معين إلى بقاء العمليات المعلقة لفترة أطول من "الفترة الزمنية القصيرة" المذكورة أعلاه. وهذا ليس بالضرورة خطأً برمجياً.
#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main ( void ) { pid_t pids [ 10 ]; int i ;for ( i = 9 ; i >= 0 ; -- i ) { pids [ i ] = fork (); if ( pids [ i ] == 0 ) { printf ( "Child%d \n " , i ); sleep ( i + 1 ); _exit ( 0 ); } }for ( i = 9 ; i >= 0 ; -- i ) { printf ( "parent%d \n " , i ); waitpid ( pids [ i ], NULL , 0 ); }return 0 ; }الناتج
parent9 الطفل 3 الطفل 4 الطفل 2 الطفل 5 الطفل 1 الطفل 6 الطفل 0 الطفل 7 الطفل 8 الطفل 9 // هناك وقفة هنا أحد الوالدين 8 parent7 الوالد 6 الوالد 5 الوالد 4 الأب 3 الوالد الثاني الوالد 1 parent0
توضيح
في الحلقة الأولى، يقوم البرنامج الأصلي (الأب) بإنشاء عشر نسخ فرعية منه. كل عملية فرعية من هذه العمليات (يتم اكتشافها من خلال حقيقة أن الدالة fork() أعادت القيمة صفر) تطبع رسالة، ثم تدخل في حالة سكون، وتخرج من الحلقة. يتم إنشاء جميع العمليات الفرعية في نفس الوقت تقريبًا (نظرًا لأن البرنامج الأصلي لا يقوم بالكثير من العمليات في الحلقة)، لذا فإن وقت جدولة كل منها لأول مرة عشوائي إلى حد ما - ومن هنا يأتي الترتيب غير المنتظم لرسائلها.
أثناء الحلقة، يتم إنشاء مصفوفة لمعرفات العمليات الفرعية. توجد نسخة من مصفوفة pids[] في جميع العمليات الإحدى عشرة، ولكنها كاملة فقط في العملية الأصلية - ستفتقر النسخة في كل عملية فرعية إلى معرفات العمليات الفرعية ذات الأرقام الأقل، وسيكون معرف العملية الخاص بها صفرًا. (مع ذلك، لا يهم هذا كثيرًا، لأن العملية الأصلية فقط هي التي تستخدم هذه المصفوفة).
تُنفَّذ الحلقة الثانية فقط في العملية الرئيسية (لأن جميع العمليات الفرعية قد انتهت قبل هذه المرحلة)، وتنتظر حتى تنتهي كل عملية فرعية. تنتظر الحلقة العملية الفرعية التي نامت لمدة 10 ثوانٍ أولًا؛ أما باقي العمليات فقد انتهت منذ فترة طويلة، لذا تظهر جميع الرسائل (باستثناء الأولى) بتتابع سريع. لا مجال هنا للترتيب العشوائي، لأن العملية مُتحكَّم بها بواسطة حلقة في عملية واحدة. في الواقع، ظهرت رسالة العملية الرئيسية الأولى قبل أي من رسائل العمليات الفرعية - فقد تمكنت العملية الرئيسية من الاستمرار في الحلقة الثانية قبل أن تتمكن أي من العمليات الفرعية من البدء. هذا مجرد سلوك عشوائي لمُجدوِل العمليات - كان من الممكن أن تظهر رسالة "parent9" في أي مكان في التسلسل قبل رسالة "parent8".
تقضي العمليات الفرعية من Child0 إلى Child8 ثانية واحدة أو أكثر في هذه الحالة، بين وقت خروجها ووقت قيام العملية الأب بتنفيذ waitpid() عليها. كانت العملية الأب تنتظر Child9 بالفعل قبل خروجها، لذا لم تقضِ هذه العملية أي وقت تقريبًا في حالة الزومبي. [ 3 ]
انظر أيضاً
مراجع
- ↑ "صفحة دليل wait(2)" . دليل مبرمج لينكس .
- ↑ "الزومبي (5) - نظام يونكس الخامس (مفاهيم)" . كاشف المصادم في مختبر فيرميلاب .
- ↑ "لينكس - هل يمكن لأحد أن يشرح كيف يعمل هذا؟ fork()، sleep()" .
- "صفحات دليل يونكس : ps()" . مساعدة يونكس للمستخدمين . مؤرشفة من الأصل بتاريخ 2013-03-08.
روابط خارجية
- عملية (حوسبة)
- استعارات تشير إلى الزومبي
