覆蓋進程映像


假設我們正在執行一個程式,想從當前程式執行另一個程式。 這可能嗎? 如果我們實現覆蓋進程映像的概念。 當前正在執行的程式呢,也可以執行的。 當前的程式與新程式疊加,如果想執行兩個程式,而不會丟失當前正在執行的程式,有可能嗎?這是可能做到的。

建立一個子進程,以便有一個父進程和一個新建立的子進程。 我們已經在父進程中執行當前程式,所以在子進程中執行新建立的進程。 這樣可以從當前程式執行另一個程式。 不僅是一個程式,而且可以通過建立許多子進程來執行當前程式中的任意數量的程式。

看看以下面的程式範例。檔案: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;
}

上面的程式中,helloworld程式將覆蓋execl_test的進程映像。 這就是執行execl_test(printf())的過程映像程式碼的原因。

編譯和執行的結果如下 -

Hello World

現在,我們將從一個程式執行以下兩個程式,即execl_run_two_prgms.c

  • Hello World程式(helloworld.c)
  • while迴圈程式從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;
}

- 放置sleep()呼叫以確保子進程和父進程順序執行(不重疊結果)。

執行上面範例程式碼,得到以下結果 -

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迴圈程式根據命令列引數(while_loop.c)從1列印到num_times_str次數。

這個程式大致執行以下操作 -

  • 建立一個子進程
  • 子進程執行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;
}

以下是從execl_run_two_prgms.c程式的子進程呼叫helloworld.c程式。

檔案:helloworld.c -

#include<stdio.h>

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

以下是從execl_run_two_prgms.c程式的父進程呼叫的while_loop.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, ...);

這個函式會覆蓋當前正在執行的進程映像和引數patharg中提到的新進程。 如果任何引數需要傳遞給新的進程映像,那麼將通過「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 [])和其他引數。