覆盖进程映像
假设我们正在运行一个程序,并且我们想从当前程序运行另一个程序。这可能吗?为什么不行,如果我们实现覆盖进程映像的概念。这很好,但是当前正在运行的程序呢,它也可以运行吗?这怎么可能呢,因为我们用新程序覆盖了当前程序。如果我想在不丢失当前正在运行的程序的情况下运行这两个程序,该怎么办?是的,这是可能的。
创建一个子进程,这样我们就有一个父进程和一个新创建的子进程。我们已经在父进程中运行当前程序,因此在子进程中运行新创建的进程。这样,我们就可以从当前程序运行另一个程序。不仅仅是单个程序,我们可以通过创建多个子进程从当前程序运行任意数量的程序。
让我们以以下程序为例。
/* 文件名:helloworld.c */
#include<stdio.h>
void main() {
printf("Hello World
");
return;
}
/* 文件名:execl_test.c */
#include<stdio.h>
#include<unistd.h>
void main() {
execl("./helloworld", "./helloworld", (char *)0);
printf("This wouldn't print
");
return;
}
上述程序会将 execl_test 的进程映像与 helloworld 重叠。因此,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 ", value);
value++;
}
printf("
");
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
");
execl("./helloworld", "./helloworld", (char *)0);
printf("This wouldn't print
");
} else { /* Parent process */
sleep(3);
printf("Parent process: Running While loop Program
");
execl("./while_loop", "./while_loop", (char *)0);
printf("Won't reach here
");
}
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 循环程序,根据命令行参数打印从 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
");
num_times = 10;
sprintf(num_times_str, "%d", num_times);
} else {
strcpy(num_times_str, argv[1]);
printf("num_times_str is %s
", num_times_str);
pid = fork();
}
/* Child process */
if (pid == 0) {
printf("Child process: Running Hello World Program
");
err = execl("./helloworld", "./helloworld", (char *)0);
printf("Error %d
", err);
perror("Execl error: ");
printf("This wouldn't print
");
} else { /* Parent process */
sleep(3);
printf("Parent process: Running While loop Program
");
execl("./while_loop", "./while_loop", (char *)num_times_str, (char *)0);
printf("Won't reach here
");
}
return;
}
以下是从程序的子进程 execl_run_two_prgms.c 调用的 helloworld.c 程序。
/* 文件名:helloworld.c */
#include<stdio.h>
void main() {
printf("Hello World
");
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
", argv[1]);
while (start_value <= end_value) {
printf("%d ", start_value);
start_value++;
}
printf("
");
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, ...);
此函数将使用参数 path 和 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[])和其他参数的问题。

