Hình ảnh Quy trình Lớp phủ

Giả sử rằng chúng ta đang chạy một chương trình và chúng ta muốn chạy một chương trình khác từ chương trình hiện tại. Điều này có khả thi không? Tại sao lại không, nếu chúng ta triển khai khái niệm chồng hình ảnh quá trình. Điều đó tốt nhưng những gì về chương trình đang chạy hiện tại, có thể chạy được luôn. Làm thế nào nó có thể, vì chúng tôi đã chồng chương trình hiện tại với chương trình mới. Muốn chạy hai chương trình mà không bị mất chương trình đang chạy thì phải làm sao? Có, nó là có thể.

Tạo một quy trình con, để chúng ta có một quy trình mẹ và một quy trình con mới được tạo. Chúng tôi đang chạy chương trình hiện tại trong quy trình mẹ, vì vậy hãy chạy quy trình mới được tạo trong quy trình con. Bằng cách này, chúng ta có thể chạy một chương trình khác từ chương trình hiện tại. Không chỉ một chương trình đơn lẻ mà chúng ta có thể chạy bất kỳ số lượng chương trình nào từ chương trình hiện tại bằng cách tạo ra nhiều quá trình con đó.

Chúng ta hãy xem xét chương trình sau đây như một ví dụ.

/ * Tên tệp: helloworld.c * /

#include<stdio.h>

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

/ * Tên tệp: executel_test.c * /

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

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

Chương trình trên sẽ phủ lên hình ảnh quá trình của executel_test với helloworld. Đó là lý do, mã hình ảnh tiến trình của executel_test (printf ()) không được thực thi.

Các bước biên dịch và thực hiện

Hello World

Bây giờ, chúng ta sẽ chạy hai chương trình sau từ một chương trình, tức là, executel_run_two_prgms.c.

  • Chương trình Hello World (helloworld.c)

  • Chương trình lặp while để in từ 1 đến 10 (while_loop.c)

/ * Tên tệp: 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;
}

Sau đây là chương trình chạy hai chương trình (một chương trình từ con và một chương trình khác từ cha).

/ * Tên tệp: executel_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;
}

Note - Đặt lệnh gọi sleep () để đảm bảo các tiến trình con và cha chạy tuần tự (không trùng lặp kết quả).

Các bước biên dịch và thực hiện

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

Bây giờ chúng ta sẽ chạy hai chương trình từ một chương trình, tức là, executel_run_two_prgms.c, chương trình tương tự như trên nhưng với các đối số dòng lệnh. Vì vậy, chúng tôi đang chạy hai chương trình cụ thể là, helloworld.c trong quy trình con và chương trình while_loop.c trong quy trình mẹ. Điều này như sau:

  • Chương trình Hello World (helloworld.c)

  • Chương trình lặp while để in từ 1 đến num_times_str theo đối số dòng lệnh (while_loop.c)

Chương trình này thực hiện rộng rãi các hành động sau:

  • Tạo quy trình con

  • Tiến trình con thực thi chương trình helloworld.c

  • Tiến trình mẹ thực thi chương trình while_loop.c truyền giá trị đối số dòng lệnh làm đối số cho chương trình. Nếu các đối số dòng lệnh không được truyền, thì giá trị mặc định được coi là 10. Ngược lại, nó nhận giá trị đối số đã cho. Giá trị đối số phải là số; mã sẽ không xác thực nếu được cung cấp trong bảng chữ cái.

/ * Tên tệp: executel_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;
}

Sau đây là chương trình helloworld.c được gọi từ tiến trình con của chương trình, executel_run_two_prgms.c.

/ * Tên tệp: helloworld.c * /

#include<stdio.h>

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

Sau đây là chương trình while_loop.c được gọi từ tiến trình mẹ của chương trình, executel_run_two_prgms.c. Đối số cho chương trình này được truyền từ chương trình chạy điều này, tức là, executel_run_two_prgms.c.

/ * Tên tệp: 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;
}

Các bước biên dịch và thực hiện

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

Bây giờ chúng ta hãy xem các hàm thư viện liên quan đến hình ảnh lớp phủ.

#include<unistd.h>

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

Hàm này sẽ phủ hình ảnh tiến trình đang chạy hiện tại với tiến trình mới như được đề cập trong các đối số, đường dẫn và đối số. Nếu bất kỳ đối số nào cần được chuyển đến một hình ảnh quy trình mới, đối số đó sẽ được gửi qua các đối số “arg” và đối số cuối cùng phải là NULL.

Hàm này sẽ chỉ trả về một giá trị trong trường hợp có lỗi. Các cuộc gọi liên quan đến lớp phủ hình ảnh của quy trình như được đề cập bên dưới:

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[]);

Các lệnh gọi này sẽ giải quyết việc truyền các đối số dòng lệnh (argv []), các biến môi trường (envp []) và các tham số khác.