exec族的任一函数都不创建一个新的进程,而是在调用进程里面去执行新的程序。所以进程id不变,还是调用exec函数前的进程id,但是用户空间的代码和数据都更新了,变为新程序的代码和数据了。
extern char **environ; //全局环境变量,导入到本文件即可直接使用
1. int execl(const char *path, const char *arg, ...);
功能:通过路径+文件名来加载一个进程;path文件路径;arg文件名称;...可变参数,至少一个NULL
附:l即list
返回值:成功的情况下是没有返回的,失败时返回-1 。
举例说明:
execl("/bin/ls", "ls", "-a", "-l", NULL); //path绝对路径,如/bin/ls;文件名称ls;后面三个可变参数,最后必须以NULL结束
2. int execlp(const char *file, const char *arg, ...);
功能:借助PATH环境变量加载一个进程,file要加载的程序的名称
附:l即list;p即path
该函数需要配合PATH环境变量来使用,当PATH中所有目录搜索后没有参数file,则出错返回。
该函数通常用来调用系统程序。如:ls、cp、cat等命令。
返回值:成功的情况下是没有返回的,失败时返回-1 。
举例说明:
execlp("ls", "ls", "-a", "-l", NULL); //第一个ls是指查看PATH环境变量里的ls;第二个ls是名称文件;后面是可变参数,NULL结束
3. int execle(const char *path, const char *arg, ..., char * const envp[]);
功能:加载指定路径的程序,并为新程序复制最后一个环境变量
附:l即list;e即environment
举例说明:
char* envp[] = {NULL};
execlp("ls", "ls", "-a", "-l", NULL, envp);
4. int execv(const char *path, char *const argv[]);
功能:加载指定路径的程序
附:v即vector,命令行参数列表
举例说明:
char* argv[] = {"ls", "-a", "-l", NULL};
execl("/bin/ls",argv);
5. int execvp(const char *file, char *const argv[]);
功能:加载path环境变量里的名称为file的程序
附:v即命令行参数列表,p即path
int main(int argc, char *argv[]) {
pid_t pid = fork();
if (pid == 0) { //子进程里加载ls程序
char* argvv[] = {"ls", "-a", "-l", NULL};
execvp("ls", argvv);
perror("execlp"); exit(1); //只有execl函数执行失败的情况下才有机会执行这两句代码,执行的成功话就有去无回了。
} else if (pid > 0) {
sleep(1); printf("parent ");
}
return 0;
}
6. int execve(const char *filename, char *const argv[], char *const envp[]);
功能:加载指定的程序;filename必须是一个可执行程序或者一个以#! interpreter [optional-arg] 开始的脚本。
上面的五个exec函数是库函数,这个是系统函数;上面的五个exec函数最终都是调用这个函数实现的。
总结:exec族函数的规律
exec函数一旦调用成功就有去无回了,去执行新的程序去了。只有失败时才有返回,返回值为-1。所以我们直接在exec函数调用后直接调用perror()和exit(),不需要if判断,因为失败的情况才会执行。
函数名的意义的理解:
l (list) 命令行参数列表
p (path) 环境变量,环境变量搜素文件名称file
v (vector) 命令行参数数组
e (environment) 环境变量数组,给新加载程序设置指定的环境变量
函数的相似性:
execlp——>execvp
|
execl ——>execv
|
execle——>execve
从左往右,可变参数转为以NULL结尾的指针数组;从左往右, 从上往下,最后归根结底都是调用execve函数实现的。