文章目录
一、概念
- 有时我们需要在子进程中执行其他程序,即替换当前进程映像,这就需要使用如下exec系列函数之一:
#include<unisted.h> extern char** environ; 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,const char* argv[]); int execvp(const char * file,const char* argv[]); int exeve(const char * path,const char* argv[],char* const envp[]);
- path参数指定可执行文件的完整路径,file参数可以接受文件名,该文件的具体位置则在环境变量path中搜寻。arg接收可变参数,argv则接收参数数组,他们都会被传递给新程序(path或file指定的程序)的main函数。envp参数用于设置新程序的环境变量。如果未设置它,则新程序将使用由全局变量environ指定的环境变量。
- 一般情况下,exec函数是不返回的,除非出错。出错时返回-1,并设置errno。如果没出错,则源程序中exec调用之后的代码都不会执行,因此此时源程序已经被exec的参数指定的程序完全替换(把偶哦代码和数据)。
- exec函数不会关闭源程序打开的文件描述符,除非文件描述符被设置了类似SOCK_CLOEXEC的属性。
二、编写示例使用exec函数替换进程映像
- 如下,把test替换为ps路径
- 首先查找ps路径
- 然后编写test.c文件,执行命令
- 执行结果可发现输出的pid=1863和-f参数状态中的pid一致,可验证替换成功
test.c内部代码:
1.按照int execl(const char * path,const char* arg,...);的库标准写:execl("/usr/bin/ps","ps","-f",(char *)0); // /usr/bin/ps: 文件路径;ps:程序名;-f:参数;((char *)0):以空结尾,类型强转
2.按照int execlp(const char * file,const char* arg,...);的库标准写:execlp("ps","ps","-f",(char *)0);//ps:程序名;-f:参数;((char *)0):以空结尾,类型强转
execlp不需要再写环境变量,系统可自己在path路径下查宅,如下所示示例PATH路径:
3.按照int execle(const char * path,const char* arg,...,char* const envp[]);的库标准写: execle("/usr/bin/ps","ps","-f",(char *)0,envp); // /usr/bin/ps: 文件路径;ps:程序名;-f:参数;(char *)0:以空结尾,类型强转;envp:采用main的环境变量;
4.按照int execv(const char * path,const char* argv[]); 的库标准写: char *myargv[]={"ps","-f",0};execv("/usr/bin/ps",myargv);// /usr/bin/ps: 文件路径;myargv:存放参数的数组;
5.按照int execvp(const char * file,const char* argv[]); 的库标准写:char *myargv[]={"ps","-f",0}; execvp("ps",myargv); // ps: 程序名;myargv:存放参数的数组;
6.按照int exeve(const char * path,const char* argv[],char* const envp[]);的库标准写:char *myargv[]={"ps","-f",0}; execve("/usr/bin/ps",myargv,envp);// /usr/bin/ps: 文件路径;myargv:存放参数的数组;envp:采用main的环境变量;
注意,当运行成功时,执行完exec函数会直接执行exit,如果失败会开始执行exec和eexit之间的代码(可以在这之间输出“execl error”的提醒)
三、exec与fork的结合使用
问:linux上创建新进程的方式是?
答:fork()+exec()
举例解释
- 例1实现当前主程序复制产生一个子进程,子进程用程序ps替换自身:
- pid==0:子进程;pid==-1fork失败
- getpid()得到子进程PID;getppid()得到父进程PPID
- 执行结果分析:
- 第一步打印了父进程和子进程
- fork()复制出子进程,打印子进程
- 子进程进行替换ps,在下图中倒数第二行和倒数第一行的PID也可看出ps -f(5249)是main(5248)的子进程。
- 例2当前主程序复制产生一个子进程,子进程用新程序"b"替换自身
- text1.c:
- b.c:
- 执行结果分析:
- 在text1执行时,执行了第一步,打印main pid;
- 然后复制子进程,子进程用新程序"b"替换自身
- 在b进程内:打印了参数个数:4,参数依次为text1.c数组myargv中写的:b,hello,abc,123,后面打印的就是环境变量..
- 子进程结束,父进程获取退出码,wait(NULL)