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\n");
}
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函数实现的。