الخميس، 1 أكتوبر 2020

إنشاء العملية وإنهاؤها

 

إنشاء العملية وإنهاؤها


Ad by Valueimpression

حتى الآن نعلم أنه عندما ننفذ برنامجًا ، يتم إنشاء عملية وسيتم إنهاؤها بعد الانتهاء من التنفيذ. ماذا لو احتجنا إلى إنشاء عملية داخل البرنامج وربما أردنا جدولة مهمة مختلفة لها. هل يمكن تحقيق ذلك؟ نعم ، من الواضح من خلال عملية الإنشاء. بالطبع ، بعد الانتهاء من المهمة ، سيتم إنهاؤها تلقائيًا أو يمكنك إنهاؤها حسب الحاجة.

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

استدعاء النظام

بعد إنشاء العملية الفرعية ، دعنا نرى تفاصيل استدعاء نظام fork ().

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

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

يُرجع استدعاء نظام fork () أيًا من القيم الثلاث -

  • القيمة السالبة للإشارة إلى خطأ ، أي عدم نجاح في إنشاء العملية الفرعية.

  • ترجع صفر للعملية الفرعية.

  • ترجع قيمة موجبة للعملية الأصل. هذه القيمة هي معرف العملية للعملية الفرعية المنشأة حديثًا.

دعونا نفكر في برنامج بسيط.

File name: basicfork.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   fork();
   printf("Called fork() system call\n");
   return 0;
}

خطوات التنفيذ

التحويل البرمجي

gcc basicfork.c -o basicfork

التنفيذ / الإخراج

Called fork() system call
Called fork() system call

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

في الحالة المذكورة أعلاه ، يتم استدعاء fork () مرة واحدة ، ومن ثم تتم طباعة الإخراج مرتين (2 power 1). إذا تم استدعاء fork () ، على سبيل المثال 3 مرات ، فسيتم طباعة الإخراج 8 مرات (2 power 3). إذا تم استدعاؤها 5 مرات ، فإنها تطبع 32 مرة وهكذا دواليك.

بعد رؤية fork () إنشاء العملية الفرعية ، فقد حان الوقت لمعرفة تفاصيل عمليات الوالدين والطفل.

اسم الملف: pids_after_fork.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   pid_t pid, mypid, myppid;
   pid = getpid();
   printf("Before fork: Process id is %d\n", pid);
   pid = fork();

   if (pid < 0) {
      perror("fork() failure\n");
      return 1;
   }

   // Child process
   if (pid == 0) {
      printf("This is child process\n");
      mypid = getpid();
      myppid = getppid();
      printf("Process id is %d and PPID is %d\n", mypid, myppid);
   } else { // Parent process 
      sleep(2);
      printf("This is parent process\n");
      mypid = getpid();
      myppid = getppid();
      printf("Process id is %d and PPID is %d\n", mypid, myppid);
      printf("Newly created process id or child pid is %d\n", pid);
   }
   return 0;
}

خطوات التجميع والتنفيذ

Before fork: Process id is 166629
This is child process
Process id is 166630 and PPID is 166629
Before fork: Process id is 166629
This is parent process
Process id is 166629 and PPID is 166628
Newly created process id or child pid is 166630

يمكن أن تنتهي العملية بإحدى الطريقتين -

  • بشكل غير طبيعي ، يحدث عند توصيل إشارات معينة ، مثل إنهاء الإشارة.

  • عادةً ، باستخدام استدعاء نظام _exit () (أو استدعاء نظام _Exit ()) أو وظيفة مكتبة exit ().

الفرق بين _exit () و exit () هو نشاط التنظيف بشكل أساسي. يقوم المخرج () ببعض عمليات التنظيف قبل إعادة عنصر التحكم مرة أخرى إلى kernel ، بينما يقوم _exit () (أو _Exit ()) بإعادة عنصر التحكم مرة أخرى إلى kernel على الفور.

خذ بعين الاعتبار البرنامج المثال التالي مع exit ().

اسم الملف: atexit_sample.c

#include <stdio.h>
#include <stdlib.h>

void exitfunc() {
   printf("Called cleanup function - exitfunc()\n");
   return;
}

int main() {
   atexit(exitfunc);
   printf("Hello, World!\n");
   exit (0);
}

خطوات التجميع والتنفيذ

Hello, World!
Called cleanup function - exitfunc()

خذ بعين الاعتبار البرنامج المثال التالي مع _exit ().

اسم الملف: at_exit_sample.c

#include <stdio.h>
#include <unistd.h>

void exitfunc() {
   printf("Called cleanup function - exitfunc()\n");
   return;
}

int main() {
   atexit(exitfunc);
   printf("Hello, World!\n");
   _exit (0);
}

خطوات التجميع والتنفيذ

Hello, World!

التسميات: