fork()创建子进程进行替换,不影响父进程,父进程聚焦在:读取数据、解析数据、指派进程、执行代码的功能。
在加载新程序进去之前,父子之间的的代码是共享的,数据写时拷贝进子进程。
当加载新程序后,也是一种写入。代码要不要拷贝呢?
重新加载后,父子的代码必须分离
下面是一个示例,展示了如何在Linux下使用exec系列命令创建子进程并运行自己写的代码,同时父进程继续执行其他任务:
#include
#include
#include
#include
int main() {
pid_t pid = fork(); // 创建子进程
if (pid == -1) {
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程中执行自己的代码
printf("Child process: Hello, I am the child process!\n");
// 使用exec系列命令运行自己的代码
execl("/path/to/your/executable", "/path/to/your/executable", NULL);
// 如果exec执行失败,则会继续执行以下代码
perror("execl");
return 1;
} else {
// 父进程继续执行其他任务
printf("Parent process: Hello, I am the parent process!\n");
// 等待子进程结束
wait(NULL);
printf("Parent process: Child process has finished.\n");
}
return 0;
}
在上面的示例中,首先使用fork
函数创建了一个子进程。子进程通过判断fork
的返回值来确定自己是子进程还是父进程。如果返回值为0,则表示是子进程,子进程中执行了自己的代码,并使用execl
命令运行自己的可执行文件。如果execl
执行成功,则子进程的代码会被替换为新的代码,否则会打印错误信息。父进程则继续执行其他任务,并使用wait
函数等待子进程结束。
请注意,上述示例中的/path/to/your/executable
需要替换为自己的可执行文件的路径。此外,还需要将自己的代码编译为可执行文件,并确保具有执行权限。
要在上述代码的基础上给子进程传递环境变量,可以使用execle
函数而不是execl
函数。execle
函数允许您指定要传递给子进程的环境变量。
下面是修改后的示例代码:
#include
#include
#include
#include
int main() {
pid_t pid = fork(); // 创建子进程
if (pid == -1) {
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程中执行自己的代码
printf("Child process: Hello, I am the child process!\n");
// 创建环境变量数组
char* envp[] = {
"VAR1=value1",
"VAR2=value2",
NULL
};
// 使用execle命令运行自己的代码,并传递环境变量
execle("/path/to/your/executable", "/path/to/your/executable", NULL, envp);
// 如果execle执行失败,则会继续执行以下代码
perror("execle");
return 1;
} else {
// 父进程继续执行其他任务
printf("Parent process: Hello, I am the parent process!\n");
// 等待子进程结束
wait(NULL);
printf("Parent process: Child process has finished.\n");
}
return 0;
}
在上述示例中,我们创建了一个envp
数组,其中包含要传递给子进程的环境变量。数组的最后一个元素必须为NULL
,以表示环境变量列表的结束。
然后,我们使用execle
函数来运行自己的可执行文件,并将环境变量数组作为参数传递给它。execle
函数的最后一个参数是一个指向环境变量数组的指针。
请确保将/path/to/your/executable
替换为自己的可执行文件的路径,并根据需要修改环境变量数组。
myproc.c
#include
#include
#include
#include
int main()
{
extern char **environ;
pid_t id = fork();
if(id == 0)
{
//child
printf("我是子进程: %d\n", getpid());
//execl: 如果替换成功,不会有返回值,如果替换失败,一定有返回值 ==》如果失败了,必定返回 ==》 只要有返回值,就失败了
//不用对该函数进行返回值判断,只要继续向后运行一定是失败的!
//execl("/bin/ls", "ls", "-a", "-ln", NULL); //lsssss: 不存在
//char *const myargv[] = {
// "ls",
// "-a",
// "-l",
// "-n",
// NULL
//};
//execv("/bin/ls", myargv); //lsssss: 不存在
//execlp("ls", "ls", "-a", "-l", "-n", NULL);
//execvp("ls", myargv);
//char *const myenv[] = {
// "MYENV=YouCanSeeMe",
// NULL
//};
//putenv("MYENV=YouCanSeeMe");
//execle("./exec/otherproc", "otherproc", NULL, environ);
//execl("./exec/shell.sh", "shell.sh", NULL);
execl("./exec/test.py", "test.py", NULL);
exit(1);
}
sleep(1);
//father
int status = 0;
printf("我是父进程: %d\n", getpid());
waitpid(id, &status, 0);
printf("child exit code: %d\n", WEXITSTATUS(status));
return 0;
}