linux之进程管理(二)--替换
2026/7/23 3:38:57 网站建设 项目流程

我们先来看一个现象

程序运行到execl这里的时候,去执行ls的命令行操作,但是并没有执行后面的代码,这是怎么回事呢???

这是我们正常的的一个进程

当我们运行execl这个函数的时候,将磁盘里面的数据加载到这个里面物理内存里面,将原来的代码和数据部分覆盖自然就看不到printf所打印出来的内容

在实践中,我们通常会让子进程来完成程序替换的过程

当父子进程都不对数据和代码修改时

当任意一方对数据发生修改时

调用程序替换函数时,将磁盘的文件加载到内存,覆盖子进程的代码和数据

至此彻底完成父子进程的分离

程序替换函数

// 1. execl​ 2int execl(const char *path, const char *arg0, ..., (char *)NULL);​ 3// 2. execlp​ 4int execlp(const char *file, const char *arg0, ..., (char *)NULL);​ 5// 3. execle​ 6int execle(const char *path, const char *arg0, ..., (char *)NULL, char *envp[]);​ 7​ 8// 4. execv​ 9int execv(const char *path, char *const argv[]);​ 10// 5. execvp​ 11int execvp(const char *file, char *const argv[]);​ 12// 6. execvpe​ 13int execvpe(const char *file, char *const argv[], char *const envp[]);​ 14​ 15// 7. execve(真正系统调用,内核接口)​ 16int execve(const char *path, char *const argv[], char *const envp[]);
字母含义
llist,参数逐个罗列,最后必须 NULL
vvector,参数放进字符串数组传参
ppath,自动搜索环境变量 PATH,不用写完整绝对路径
eenv,手动传入自定义环境变量数组
通用特性(全部 7 个函数一致)
  1. 成功永不返回,原程序代码全部被覆盖,后面代码不执行;

  2. 失败返回-1,可 perror 打印错误;

  3. 不创建新进程,PID 不变,仅替换当前进程运行程序;

  4. 已打开的文件描述符默认继承(除非设置 FD_CLOEXEC)。

详细说明

execl
// 1. execl int execl(const char *path, const char *arg0, ..., (char *)NULL);

#include<stdio.h> 2 #include<unistd.h> 3 #include<sys/wait.h> 4 #include<stdlib.h> 5 int main() 6 { 7 printf("我是父进程,pid:%d\n",getpid()); 8 printf("========================================\n"); 9 pid_t id=fork(); 10 if(id==0){ 11 printf("下面是子进程执行的代码\n"); 12 execl("/bin/ls","ls","-l",NULL); 13 } 14 int status=0; 15 pid_t rid=waitpid(-1,&status,0); 16 if(rid>0) 17 { 18 printf("========================================\n"); 19 printf("成功回收子进程\n"); 20 } 21 return 0; 22 }

execlp
// 2. execlp int execlp(const char *file, const char *arg0, ..., (char *)NULL);

if(id==0) { printf("下面是子进程执行的代码\n"); execlp("ls","ls",NULL); }

execv
// 4. execv int execv(const char *path, char *const argv[]);

if(id==0) { printf("下面是子进程执行的代码\n"); char *const argv[]= { "ls","-a","-l","--color=auto" ,NULL}; execv("/bin/ls",argv); }

execvp
// 5. execvp int execvp(const char *file, char *const argv[]);

if(id==0) { printf("下面是子进程执行的代码\n"); char *const argv[]= { "ls","--color=auto" ,NULL}; execvp("ls",argv); }

在上面的案例中都是用系统的,那能不能用我们直接写的可执行文件呢???

显然是可以的

if(id==0){ printf("下面是子进程执行的代码\n"); execl("./test/Replace.exe","Replace",NULL); }

execvpe
// 6. execvpe int execvpe(const char *file, char *const argv[], char *const envp[]);

e就是要我们手动传入环境变量和之前没有e的又有什么区别吗??

一个通俗比喻
  • 父进程手里有一整本资料(所有环境变量:PATH、HOME、USER……)

  • execvp(无 e):直接复印整本资料交给新程序

  • execvpe(有 e):旧资料作废,你亲手写一张新纸条交给新程序。 纸条上必须写上 PATH,否则新程序找不到 ls。

if(id==0) { printf("下面是子进程执行的代码\n"); char *const argv[]= { "testEnviron.exe","-a","-c","6" ,NULL}; char *envp[] ={"PATH=/home/pineapple/pineapple_dir/linux-learning/processReplace/test",NULL }; extern char **environ; execvpe("./test/testEnviron.exe",argv,environ); //execvpe("./test/testEnviron.exe",argv,envp); perror("execvpe 调用失败原因"); _exit(1); }

使用我们自己传入的环境变量

if(id==0) { printf("下面是子进程执行的代码\n"); char *const argv[]= { "testEnviron.exe","-a","-c","6" ,NULL}; char *envp[] ={"PATH=/home/pineapple/pineapple_dir/linux-learning/processReplace/test",NULL }; execvpe("./test/testEnviron.exe",argv,envp); perror("execvpe 调用失败原因"); _exit(1); }

在原来老的环境变量上面加上新的环境变量

if(id==0) { printf("下面是子进程执行的代码\n"); char *const argv[]= { "testEnviron.exe","-a","-c","6" ,NULL}; char *envp[] ={"PATH=/home/pineapple/pineapple_dir/linux-learning/processReplace/test",NULL }; extern char **environ; putenv("PATH=/home/pineapple/pineapple_dir/linux-learning/processReplace/test"); execvpe("./test/testEnviron.exe",argv,environ); // execvpe("./test/testEnviron.exe",argv,envp); perror("execvpe 调用失败原因"); _exit(1); }

剩下来大同小异,这里不做过多介绍.

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询