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

عمليات أخرى

 

عمليات أخرى


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

عملية اليتيم

كما هو مبين بالاسم ، اليتيم يعني عملية بدون أبوين. عندما نقوم بتشغيل برنامج أو تطبيق ، فإن العملية الرئيسية للتطبيق هي shell. عندما نقوم بإنشاء عملية باستخدام fork () ، فإن العملية التي تم إنشاؤها حديثًا هي العملية الفرعية والعملية التي خلقت الطفل هي العملية الأم. في المقابل ، فإن العملية الأم لهذا هي قذيفة. بالطبع ، أصل جميع العمليات هو عملية البادئ (معرف العملية → 1).

ما سبق هو السيناريو المعتاد ، ومع ذلك ، ماذا يحدث إذا خرجت العملية الأب قبل العملية الفرعية. والنتيجة هي أن العملية الفرعية أصبحت الآن العملية اليتيمة. ثم ماذا عن الشركة الأم ، فإن والدها الجديد هو الأصل لجميع العمليات ، والتي ليست سوى عملية بادئة (معرف العملية - 1).

دعونا نحاول فهم ذلك باستخدام المثال التالي.

/ * اسم الملف: orphan_process.c * /

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

int main() {
   int pid;
   system("ps -f");
   pid = fork();
   if (pid == 0) {
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(5);
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      system("ps -f");
   } else {
      printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(2);
      exit(0);
   }
   return 0;
}

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

UID         PID   PPID  C STIME TTY    TIME CMD
4581875  180558      0  0 09:19  ?     00:00:00 sh -c cd /home/cg/root/4581875; 
                                       timeout 10s main
4581875  180564 180558  0 09:19  ?     00:00:00 timeout 10s main
4581875  180565 180564  0 09:19  ?     00:00:00 main
4581875  180566 180565  0 09:19  ?     00:00:00 ps -f
Parent: pid is 180565 and ppid is 180564
UID         PID   PPID  C STIME TTY    TIME CMD
4581875  180567      0  0 09:19  ?     00:00:00 main
4581875  180820 180567  0 09:19  ?     00:00:00 ps -f
Child: pid is 180567 and ppid is 180565
Child: pid is 180567 and ppid is 0

عملية الزومبي

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

دعونا نفهم هذا بمساعدة مثال.

/ * اسم الملف: zombie_process.c * /

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

int main() {
   int pid;
   pid = fork();
   if (pid == 0) {
      system("ps -f");
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      exit(0);
   } else {
      printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(10);
      system("ps aux|grep Z");
   }
   return 0;
}

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

UID         PID   PPID  C STIME TTY    TIME CMD
4581875  184946      0  0 09:20  ?     00:00:00 sh -c cd /home/cg/root/4581875; 
                                       timeout 10s main
4581875  184952 184946  0 09:20  ?     00:00:00 timeout 10s main
4581875  184953 184952  0 09:20  ?     00:00:00 main
4581875  184954 184953  0 09:20  ?     00:00:00 main
4581875  184955 184954  0 09:20  ?     00:00:00 ps -f
Child: pid is 184954 and ppid is 184953

عملية الخفي

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

تنتهي عمليات Linux الخفية الداخلية عادةً بالحرف "d" مثل Kernel Daemons (ksoftirqd، kblockd، kswapd، إلخ.)، Printing Daemons (cupsd، lpd، إلخ.)، File Service Daemons (smbd، nmbd، إلخ.) ، شياطين قاعدة البيانات الإدارية (ypbind ، ypserv ، إلخ.) ، البريد الإلكتروني Daemons (sendmail ، popd ، smtpd ، إلخ) ، تسجيل الدخول عن بُعد وتنفيذ الأوامر (sshd ، in.telnetd ، إلخ) ، شيطان التشغيل والتهيئة (dhcpd ، udevd، إلخ.)، عملية init (init)، cron daemon، atd daemon، إلخ.

الآن دعونا نرى كيفية إنشاء عملية خفية. فيما يلي الخطوات -

الخطوة 1 - إنشاء عملية فرعية. الآن لدينا عمليتان - العملية الأم والعملية الفرعية

عادةً ما يكون التسلسل الهرمي للعملية هو SHELL ← عملية الوالدين ← عملية الطفل

الخطوة 2 - إنهاء العملية الأصلية عن طريق الخروج. تصبح العملية الفرعية الآن العملية اليتيمة ويتم الاستيلاء عليها بواسطة عملية init.

الآن ، التسلسل الهرمي هو INIT PROCESS → CHILD PROCESS

الخطوة 3 - يؤدي استدعاء استدعاء نظام setid () إلى إنشاء جلسة جديدة ، إذا لم تكن عملية الاستدعاء قائد مجموعة عملية. الآن تصبح عملية الاتصال قائد المجموعة للجلسة الجديدة. ستكون هذه العملية هي العملية الوحيدة في مجموعة العمليات الجديدة هذه وفي هذه الجلسة الجديدة.

الخطوة 4 - اضبط معرف مجموعة العملية ومعرف الجلسة على PID لعملية الاستدعاء.

الخطوة 5 - أغلق واصفات الملفات الافتراضية (الإدخال القياسي والمخرج القياسي والخطأ القياسي) للعملية حيث تم الآن فصل المحطة الطرفية والصدفة عن التطبيق.

/ * اسم الملف: daemon_test.c * /

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[]) {
   pid_t pid;
   int counter;
   int fd;
   int max_iterations;
   char buffer[100];
   if (argc < 2)
   max_iterations = 5;
   else {
      max_iterations = atoi(argv[1]);
      if ( (max_iterations <= 0) || (max_iterations > 20) )
      max_iterations = 10;
   }
   pid = fork();
   
   // Unable to create child process
   if (pid < 0) {
      perror("fork error\n");
      exit(1);
   }
   
   // Child process
   if (pid == 0) {
      fd = open("/tmp/DAEMON.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
      if (fd == -1) {
         perror("daemon txt file open error\n");
         return 1;
      }
      printf("Child: pid is %d and ppid is %d\n", getpid(), getppid());
      printf("\nChild process before becoming session leader\n");
      sprintf(buffer, "ps -ef|grep %s", argv[0]);
      system(buffer);
      setsid();
      printf("\nChild process after becoming session leader\n");
      sprintf(buffer, "ps -ef|grep %s", argv[0]);
      system(buffer);
      close(STDIN_FILENO);
      close(STDOUT_FILENO);
      close(STDERR_FILENO);
   } else {
      printf("Parent: pid is %d and ppid is %d\n", getpid(), getppid());
      printf("Parent: Exiting\n");
      exit(0);
   }
   
   // Executing max_iteration times
   for (counter = 0; counter < max_iterations; counter++) {
      sprintf(buffer, "Daemon process: pid is %d and ppid is %d\n", getpid(), getppid());
      write(fd, buffer, strlen(buffer));
      sleep(2);
   }
   strcpy(buffer, "Done\n");
   write(fd, buffer, strlen(buffer));
   
   // Can't print this as file descriptors are already closed
   printf("DoneDone\n");
   close(fd);
   return 0;
}

Parent: pid is 193524 and ppid is 193523
Parent: Exiting
4581875  193525      0  0 09:23  ?      00:00:00 main
4581875  193526 193525  0 09:23  ?      00:00:00 sh -c ps -ef|grep main
4581875  193528 193526  0 09:23  ?      00:00:00 grep main
4581875  193525      0  0 09:23  ?      00:00:00 main
4581875  193529 193525  0 09:23  ?      00:00:00 sh -c ps -ef|grep main
4581875  193531 193529  0 09:23  


التسميات: