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

تراكب صورة العملية

 

تراكب صورة العملية

Ad by Valueimpression

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

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

دعونا نعتبر البرنامج التالي كمثال.

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

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

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

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

void main() {
   execl("./helloworld", "./helloworld", (char *)0);
   printf("This wouldn't print\n");
   return;
}

سيغطي البرنامج أعلاه صورة عملية execl_test مع helloworld. هذا هو السبب ، لا يتم تنفيذ كود صورة العملية لـ execl_test (printf ()).

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

Hello World

الآن ، سنقوم بتشغيل البرنامجين التاليين من برنامج واحد ، أي execl_run_two_prgms.c.

  • برنامج Hello World (helloworld.c)

  • برنامج while loop للطباعة من 1 إلى 10 (while_loop.c)

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

/* Prints numbers from 1 to 10 using while loop */
#include<stdio.h>

void main() {
   int value = 1;
   while (value <= 10) {
      printf("%d\t", value);
      value++;
   }
   printf("\n");
   return;
}

فيما يلي برنامج لتشغيل برنامجين (برنامج من طفل وآخر من الوالدين).

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

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

void main() {
   int pid;
   pid = fork();
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      execl("./helloworld", "./helloworld", (char *)0);
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

ملاحظة - ضع اتصال السكون () للتأكد من أن عمليات الطفل والوالد تعمل بالتتابع (لا تتداخل مع النتيجة).

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

Child process: Running Hello World Program
This wouldn't print
Parent process: Running While loop Program
Won't reach here

سنقوم الآن بتشغيل برنامجين من برنامج واحد ، مثل execl_run_two_prgms.c ، نفس البرنامج المذكور أعلاه ولكن مع وسيطات سطر الأوامر. لذلك ، نحن ندير برنامجين هما helloworld.c في عملية الطفل ، والبرنامج while_loop.c في عملية الوالدين. هذا كالتالي -

  • برنامج Hello World (helloworld.c)

  • برنامج while loop للطباعة من 1 إلى num_times_str حسب وسيطات سطر الأوامر (while_loop.c)

يقوم هذا البرنامج على نطاق واسع بتنفيذ الإجراءات التالية -

  • يخلق عملية الطفل

  • عملية الطفل تنفذ برنامج helloworld.c

  • يتم تنفيذ العملية الأصلية while_loop.c يقوم البرنامج بتمرير قيمة وسيطة سطر الأوامر كوسيطة للبرنامج. إذا لم يتم تمرير وسيطات سطر الأوامر ، فسيتم اعتبار القيمة الافتراضية 10. وإلا ، فإنها تأخذ قيمة الوسيطة المحددة. يجب أن تكون قيمة الوسيطة رقمية ؛ لن يتم التحقق من صحة الرمز إذا تم تقديمه بالأبجديات

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

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

void main(int argc, char *argv[0]) {
   int pid;
   int err;
   int num_times;
   char num_times_str[5];
   
   /* In no command line arguments are passed, then loop maximum count taken as 10 */
   if (argc == 1) {
      printf("Taken loop maximum as 10\n");
      num_times = 10;
      sprintf(num_times_str, "%d", num_times);
   } else {
      strcpy(num_times_str, argv[1]);
      printf("num_times_str is %s\n", num_times_str);
      pid = fork();
   }
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      err = execl("./helloworld", "./helloworld", (char *)0);
      printf("Error %d\n", err);
      perror("Execl error: ");
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)num_times_str, (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

فيما يلي برنامج helloworld.c الذي تم استدعاؤه من العملية الفرعية للبرنامج ، execl_run_two_prgms.c.

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

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

فيما يلي برنامج while_loop.c الذي تم استدعائه من العملية الرئيسية للبرنامج ، execl_run_two_prgms.c. يتم تمرير الوسيطة إلى هذا البرنامج من البرنامج الذي يدير هذا ، أي execl_run_two_prgms.c.

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

#include<stdio.h>

void main(int argc, char *argv[]) {
   int start_value = 1;
   int end_value;
   if (argc == 1)
   end_value = 10;
   else
   end_value = atoi(argv[1]);
   printf("Argv[1] is %s\n", argv[1]);
   while (start_value <= end_value) {
      printf("%d\t", start_value);
      start_value++;
   }
   printf("\n");
   return;
}

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

Taken loop maximum as 10
num_times_str is 10
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 10
1 2 3 4 5 6 7 8 9 10
Taken loop maximum as 15
num_times_str is 15
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

دعونا الآن نرى وظائف مكتبة الصور المتراكبة ذات الصلة.

#include<unistd.h>

int execl(const char *path, const char *arg, ...);

ستعمل هذه الوظيفة على تراكب صورة العملية الجارية الحالية مع العملية الجديدة كما هو مذكور في الوسيطات والمسار والحج. إذا كانت هناك حاجة إلى تمرير أي وسيطة إلى صورة عملية جديدة ، فسيتم إرسالها من خلال وسيطات "arg" ويجب أن تكون الوسيطة الأخيرة NULL.

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

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

ستتناول هذه الاستدعاءات تمرير وسيطات سطر الأوامر (argv []) ومتغيرات البيئة (envp []) ومعلمات أخرى.


التسميات: