我与Linux的爱恋:进程程序替换
🔥个人主页:guoguoqiang. 🔥专栏:Linux的学习
文章目录
- 进程程序替换
- 替换函数
- 替换原理
- 多进程替换
- exec*函数使用
- 替换函数总结
进程程序替换
替换函数
有六种以exec开头的函数,统称exec函数。
#include <stdio.h>
#include <unistd.h>int main(){printf("testexec ...begin!\n");execl("/usr/bin/ls","ls","-a","-l",NULL);printf("testexec ...end!\n");return 0;
}
execl被ls替换了,替换也是完完全全的,不会执行后面的代码。
替换原理
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数
以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动
例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
站在被替换进程的角度:本质就是这个程序被加载到内存中了;通过exec*加载函数。
多进程替换
fork创建子进程,让自进程自己去替换
创建子进程的目的是让子进程完成任务:1.让子进程执行父进程代码的一部分 2.让子进程执行一个新的程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){printf("testexec ...begin!\n");pid_t id=fork();if(id==0){printf("child pid: %d\n",getpid());sleep(2);execl("/usr/bin/ls","ls","-a","-l",NULL);exit(1);}//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));}printf("testexec ...end!\n");return 0;
}
即使是父子也要保证独立性,以前是父子共享一块空间,需要时时对数据段进行写实拷贝,现在是完完全全开辟新的空间,保证进程的独立性。
exec*函数使用
1.execl
函数原型,在前面我们已经使用过了,这里不过多介绍。关于exec*函数,我们不考虑它的返回值
int execl(const char *path, const char *arg, ...);
这里的 l 可以理解为list,path传入绝对路径,arg可变参数,依次传入命令,以及你想执行的指令,最后一个必须为NULL
2.execv
函数原型:
int execv(const char *path, char *const argv[]);
这里的v可以理解为vector,argv是一个指针数组,我们可以直接来使用
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){printf("testexec ...begin!\n");pid_t id=fork();if(id==0){printf("child pid: %d\n",getpid());sleep(2);char *const argv[]={(char*)"ls",(char*)"-l",(char*)"-a",(char*)"--color",NULL};execv("/usr/bin/ls",argv);exit(1);}//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));}printf("testexec ...end!\n");return 0;
}
3.execvp
函数原型:
int execvp(const char *file, char *const argv[]);
用户可以不传要执行的文件的路径(但是文件名要传),直接告诉exec*,我要执行谁都行
p:查找这个程序,系统会自动在环境变量PATH中进行查找
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){printf("testexec ...begin!\n");pid_t id=fork();if(id==0){printf("child pid: %d\n",getpid());sleep(2);char *const argv[]={(char*)"ls",(char*)"-l",(char*)"-a",(char*)"--color",NULL};execvp("ls",argv);exit(1);}//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));}printf("testexec ...end!\n");return 0;
}
4.execvpe
函数原型:
int execvpe(const char *file, char *const argv[],char *const envp[]);
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){printf("testexec ...begin!\n");pid_t id=fork();if(id==0){printf("child pid: %d\n",getpid());sleep(2);char *const argv[]={(char*)"ls",(char*)"-a",(char*)"-l",(char*)"--color",NULL};extern char** environ;execvpe("ls",argv,environ);exit(1);//execl("/usr/bin/ls","ls","-a","-l",NULL);//execv("/usr/bin/ls",argv);//execvp("ls",argv);}//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));}printf("testexec ...end!\n");return 0;
}
execlp和execlpe
方法与上面相同。
替换函数总结
这些函数之间的关系如下图所示
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){printf("testexec ...begin!\n");pid_t id=fork();if(id==0){putenv("AAAA=11111232154");// 我的父进程本身就有一批环境变量!!!, 从bash来printf("child pid: %d\n",getpid());sleep(2);char *const argv[]={(char*)"ls",(char*)"-a",(char*)"-l",(char*)"--color",NULL};extern char** environ;// execvpe("ls",argv,environ);//exit(1);//execl("/usr/bin/ls","ls","-a","-l",NULL);//execv("/usr/bin/ls",argv);//execvp("ls",argv);execl("/usr/bin/python3","python3","test.py",NULL);}//fatherint status=0;pid_t rid=waitpid(id,&status,0);if(rid>0){printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));}printf("testexec ...end!\n");return 0;
}
print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")