نظام شوكة نداء لينكس

Fork System Call Linux



يتم استخدام استدعاء نظام الشوكة لإنشاء عمليات جديدة. العملية التي تم إنشاؤها حديثًا هي العملية التابعة. العملية التي تستدعي الانقسام وتخلق عملية جديدة هي العملية الأصلية. يتم تنفيذ العمليات الفرعية والأصل بشكل متزامن.

لكن عمليات الطفل والوالد تقع في مساحات ذاكرة مختلفة. تحتوي مساحات الذاكرة هذه على نفس المحتوى وأي عملية يتم تنفيذها بواسطة عملية واحدة لن تؤثر على العملية الأخرى.







عندما يتم إنشاء العمليات التابعة ؛ الآن ستحتوي كلتا العمليتين على نفس عداد البرنامج (PC) ، لذلك ستشير هاتان العمليتان إلى نفس التعليمات التالية. ستكون الملفات التي يتم فتحها بواسطة العملية الرئيسية هي نفسها بالنسبة لعملية الطفل.



العملية الفرعية هي نفسها العملية الرئيسية تمامًا ولكن هناك اختلاف في معرفات العمليات:



  1. معرّف العملية للعملية الفرعية هو معرّف عملية فريد يختلف عن معرّف جميع العمليات الحالية الأخرى.
  2. سيكون معرّف العملية الأصل هو نفسه معرّف العملية لوالد الطفل.

خصائص عملية الطفل

فيما يلي بعض الخصائص التي تحتفظ بها العملية الفرعية:





  1. تتم تهيئة عدادات وحدة المعالجة المركزية واستخدامات الموارد لإعادة التعيين إلى الصفر.
  2. عند إنهاء العملية الأصل ، لا تتلقى العمليات الفرعية أي إشارة لأنه تمت إعادة تعيين سمة PR_SET_PDEATHSIG في prctl ().
  3. الخيط المستخدم لاستدعاء fork () ينشئ العملية التابعة. لذلك سيكون عنوان العملية الفرعية هو نفسه عنوان الوالد.
  4. يتم توارث واصف ملف العملية الأصلية بواسطة العملية الفرعية. على سبيل المثال ، سيتم مشاركة إزاحة الملف أو حالة العلامات وسمات الإدخال / الإخراج بين واصفات الملفات للعمليات الفرعية والعملية الرئيسية. لذا فإن واصف الملف الخاص بالفئة الرئيسية سوف يشير إلى نفس واصف الملف الخاص بالفئة الفرعية.
  5. يتم توارث واصفات قائمة انتظار الرسائل المفتوحة للعملية الأصل بواسطة العملية التابعة. على سبيل المثال ، إذا كان واصف الملف يحتوي على رسالة في العملية الرئيسية ، فستكون نفس الرسالة موجودة في واصف الملف المقابل للعملية الفرعية. لذلك يمكننا القول أن قيم العلم الخاصة بأوصاف الملفات هذه هي نفسها.
  6. وبالمثل ، سيتم توارث تدفقات الدليل المفتوح من خلال العمليات التابعة.
  7. قيمة فتره السماح المؤقت للفئة الفرعية هي نفس قيمة فتره السماح للمؤقت الحالي للفئة الأصل.

الخصائص التي لا يتم توريثها بواسطة عملية الطفل

فيما يلي بعض الخصائص التي لا تكتسبها عملية فرعية:

  1. أقفال الذاكرة
  2. الإشارة المعلقة للفئة الفرعية فارغة.
  3. عمليات تأمين السجلات المرتبطة بالعملية (fcntl ())
  4. عمليات الإدخال / الإخراج غير المتزامنة ومحتويات الإدخال / الإخراج.
  5. إخطارات تغيير الدليل.
  6. لا يتم توريث الموقتات مثل المنبه () ، setitimer () بواسطة فئة الطفل.

شوكة () في ج

لا توجد وسيطات في fork () ونوع الإرجاع fork () هو عدد صحيح. يجب عليك تضمين ملفات الرأس التالية عند استخدام fork ():



#يشمل
#يشمل
#يشمل

عند العمل مع fork () ، يمكن استخدامها للكتابة pid_t لمعرف العمليات كما تم تعريف pid_t في.

ملف الرأس هو المكان الذي يتم فيه تعريف fork () ، لذا يجب عليك تضمينه في برنامجك لاستخدام fork ().

يتم تعريف نوع الإرجاع في و fork () call. لذلك ، تحتاج إلى تضمين كليهما في برنامجك لاستخدام استدعاء نظام fork ().

صيغة الشوكة ()

صيغة استدعاء نظام fork () في Linux ، Ubuntu هي كما يلي:

pid_t fork (باطل) ؛

في بناء الجملة ، يكون نوع الإرجاع pid_t . عندما يتم إنشاء العملية الفرعية بنجاح ، يتم إرجاع PID للعملية الفرعية في العملية الأصلية وسيتم إرجاع 0 إلى العملية الفرعية نفسها.

إذا كان هناك أي خطأ ، فسيتم إرجاع -1 إلى العملية الأصلية ولا يتم إنشاء العملية الفرعية.

No arguments are passed to fork(). 

مثال 1: Calling fork ()

ضع في اعتبارك المثال التالي الذي استخدمنا فيه استدعاء النظام fork () لإنشاء عملية فرعية جديدة:

الشفرة:

#يشمل
#يشمل
#يشمل

intالأساسية()
{
شوكة()؛
printf (استخدام استدعاء نظام fork ()ن')؛
إرجاع 0؛
}

انتاج:

باستخدام استدعاء نظام fork ()
باستخدام استدعاء نظام fork ()

في هذا البرنامج ، استخدمنا fork () ، سيؤدي ذلك إلى إنشاء عملية تابعة جديدة. عندما يتم إنشاء العملية الفرعية ، ستشير كل من العملية الأصلية والعملية الفرعية إلى التعليمات التالية (نفس عداد البرامج). وبهذه الطريقة ، سيتم تنفيذ التعليمات المتبقية أو عبارات C بإجمالي عدد مرات المعالجة ، أي 2نمرات ، حيث n هو عدد استدعاءات نظام fork ().

لذلك عند استخدام استدعاء fork () مرة واحدة على النحو الوارد أعلاه (21= 2) سيكون لدينا ناتجنا مرتين.

هنا عند استخدام استدعاء نظام fork () ، سيبدو الهيكل الداخلي كما يلي:

ضع في اعتبارك الحالة التالية التي تم فيها استخدام fork () 4 مرات:

الشفرة:

#يشمل
#يشمل
#يشمل

intالأساسية()
{
شوكة()؛
شوكة()؛
شوكة()؛
شوكة()؛
printf ('استخدام استدعاء نظام fork ()')؛
إرجاع 0؛
}

انتاج:

Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call Using fork() system call 

الآن العدد الإجمالي للعملية التي تم إنشاؤها هو 24= 16 ونفذت تعليمة print الخاصة بنا 16 مرة.

مثال 2: اختبار ما إذا كانت fork () ناجحة

في المثال التالي ، استخدمنا بنية اتخاذ القرار لاختبار القيمة (int) التي تم إرجاعها بواسطة fork (). ويتم عرض الرسائل المقابلة:

الشفرة:

#يشمل
#يشمل
#يشمل

intالأساسية()
{
pid_t ص؛
ص=شوكة()؛
لو(ص== -1)
{
printf ('حدث خطأ أثناء استدعاء fork ()')؛
}
لو(ص==0)
{
printf ('نحن في عملية الطفل')؛
}
آخر
{
printf ('نحن في عملية الوالدين')؛
}
إرجاع 0؛
}

انتاج:

نحن في عملية الوالدين
نحن في عملية الطفل

في المثال أعلاه ، استخدمنا النوع pid_t الذي سيخزن قيمة إرجاع fork (). fork () يسمى على الخط:

ص=شوكة()؛

لذلك يتم تخزين قيمة العدد الصحيح الذي تم إرجاعه بواسطة fork () في p ثم تتم مقارنة p للتحقق مما إذا كانت استدعاء fork () الخاص بنا ناجحًا.

عندما يتم استخدام استدعاء fork () ويتم إنشاء الطفل بنجاح ، سيتم إرجاع معرف العملية الفرعية إلى العملية الأبوية وسيتم إرجاع 0 إلى العملية الفرعية. لن يكون معرف العملية التابعة في عملية الأصل هو نفسه معرّف العملية التابعة في العملية التابعة نفسها. في عملية الطفل ، سيكون معرّف العملية التابعة 0.

باستخدام هذا البرنامج التعليمي ، يمكنك معرفة كيفية بدء استدعاء نظام fork في نظام Linux.