文章目录
- 1.进程替换
- 2.替换过程
- 3.替换函数exec
- 3.1命名解释
- 4.细说6个exe函数
- execl函数
- execv
- execlp、execvp
- execle、execve
1.进程替换
fork()函数在创建子进程后,子进程如果想要执行一个新的程序,就可以使用进程的程序替换来完成。
程序替换是通过特定的接口,加载磁盘上的一个全新的程序(代码和数据),加载到调用进程的地址空间中。
2.替换过程
创建子进程后,子进程可以通过调用exec函数,来执行另一个程序。当程序调用exec函数时,该进程的用户空间代码和数据完完全全被新程序所替换,从新程序的启动开始执行。调用exec函数并不创建新进程,所以该进程前后的id并未改变。
3.替换函数exec
实际上有六种以exec开头的函数,统称exec函数:
#include <unistd.h>
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 execve(const char *path, char *const argv[], char *const envp[]);
- 这些函数调用成功则加载新的程序从启动代码开始执行,不在返回。
- 如果调用失败返回-1。
- exec函数只有出错才有返回值。
参数
- filename / pathname:
filename:指定文件名作参数(filename当参数时,包含"/"会在指定路径查找,不然按照PATH环境变量在指定路径目录查看可执行文件)
pathname:指定环境变量路径作参数(路径名+程序)
- 函数表传参:
函数execl、execlp以及execle要求新程序的每一个命令行参数都说明一个单独的参数,参数表以空指针结尾,一般方法:
> char *arg(), char *argl, ..., char *argn, (char *)0
这种语法说明了最后一个命令行参数之后跟一个空指针,如果用常量0表示,需要将它强制转换成一个空指针,不然它将被解释成整形参数,(比如上面:ls -l -a 被解释成 ls -l -a 0),如果一个整形的长度与char*的长度不同,那么exec函数的实际参数将出错。
其余4个函数,则先构造一个指向各参数的指针数组,然后将该数组指针地址作为这4个函数的参数。
- 环境变量表传参
以e结尾的三个函数:execle、execve、fexecve:可以传递一个指向环境字符串指针数组的指针。
3.1命名解释
- l(list):表示参数采用列表
- v(vector):参数用数组
- p(path):有p自动搜索环境变量PATH
- e(env):表示自己维护环境变量
4.细说6个exe函数
execl函数
原型:
int execl(const char *path, const char *arg, ...);
解释:
- path:表示PATH环境变量路径
- arg:表示执行什么命令
- …:可变参数列表,可以传多个参数
例子:
execv
原型:
int execv(const char *path, char *const argv[]);
解释:
- 与execl不同,execv传递的是一个char* const的数组,而execl传递的是一个个const char*
- v表示的就是数组
例子:
execlp、execvp
原型:
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
解释:
结尾有p,表示自动搜索环境变量,不需要写路径,写文件路径就好。
实列:
execlp
execvp
execle、execve
以e结尾是要进行自己组装环境变量
原型:
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execve(const char *filename, char *const argv[],char *const envp[]);
解释:
- env是我们传递的全新的环境变量,对于env我们可以传递父进程的环境变量,也可以在父进程的环境变量上新增。
- 可以通过getenv()函数获取环境变量
#include <stdlib.h>
char *getenv(const char *name);
实例:
execle
execvpe