覆蓋程序映像



假設我們正在執行一個程式,並且想要從當前程式執行另一個程式。這是可能的嗎?如果不實現覆蓋程序映像的概念,為什麼不可能?這樣是可以的,但是當前正在執行的程式呢,它還能執行嗎?這怎麼可能,因為我們用新程式覆蓋了當前程式。如果我想執行這兩個程式而不丟失當前正在執行的程式,該怎麼辦,這可能嗎?是的,這是可能的。

建立一個子程序,以便我們有一個父程序和一個新建立的子程序。我們已經在父程序中運行了當前程式,因此在子程序中執行新建立的程序。這樣,我們就可以從當前程式執行另一個程式。不僅可以執行單個程式,還可以透過建立多個子程序來從當前程式執行任意數量的程式。

讓我們以以下程式為例。

/* 檔名: 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)

  • 列印 1 到 10 的 while 迴圈程式 (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)

  • 根據命令列引數列印 1 到 num_times_str 的 while 迴圈程式 (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;
}

以下是 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, ...);

此函式將用引數(路徑和 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[]) 和其他引數的問題。

廣告

© . All rights reserved.