其实有六种以exec开头的函数,统称exec函数:
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[]);
以上函数包含在头文件#include <unistd.h>中
注意:这些函数的返回值与以往的有所不同。
如果调用成功则加载新的程序从启动代码开始执行,不再返回,
如果调用出错则 返回-1,
所以exec函数只有出错的返回值而没有成功的返回值。
如何记忆以上的函数呢?下面对函数及形参做以说明。
1.不带字母p(path)的函数:第一个参数(path)必须是程序的相对路径或绝对路径。
例如:“/bin/ls”而不是“ls”。
对于带字母p的函数:第一个参数(file)是程序名。
例如:“ls”
2.带有字母l(list)的函数:要求将新程序的每个命令行参数都当做一个参数传给它。其命令行参数是可变的,最后 一个可变参数必须以NULL结尾。
带有字母v(vector)的函数:先要构造一个指向各参数的指针数组。然后将该数组的首地址当做参数传给它。数 组中的最后一个指针是NULL。
注意:l,v是不共存的。二者只能选其一。
3.带有字母e(environment)的函数:可以把一份新的环境变量表传给它。首先要构造一个指针数组,然后将数组穿进 去。数组中的最后一个指针是NULL。
exec函数组其他5个函数底层都是调用execve函数的。
execl函数举例:(以下测试代码都是在centos下测试的)
结果为:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main()
6 {
7
8 pid_t id=fork();
9 if(id==0)//child
10 {
11 printf("this is child.pid:%d ppid:%d\n",getpid(),getppid());
12 sleep(3);
13 execl("/bin/ls","ls","-a","-i","-n",NULL);
14 printf("child end;\n");
15 }
16 else
17 {
18
19 printf("this is father.pid:%d ppid:%d\n",getpid(),getppid());
20 pid_t ret=waitpid(id,NULL,0);
21 if(ret>0)
22 printf("wait success!ret:%d\n",ret);
23 }
24
25
26 }
结果为:
execlp函数测试:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main()
6 {
7
8 pid_t id=fork();
9 if(id==0)//child
10 {
11 printf("this is child.pid:%d ppid:%d\n",getpid(),getppid());
12
13 execlp("ls","ls","-a","-i","-n",NULL);
14 printf("child end;\n");
15 }
16 else
17 {
18
19 printf("this is father.pid:%d ppid:%d\n",getpid(),getppid());
20 pid_t ret=waitpid(id,NULL,0);
21 if(ret>0)
22 printf("wait success!ret:%d\n",ret);
23 }
24
25
26 }
结果为:
execv函数:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main()
6 {
7
8 pid_t id=fork();
9 if(id==0)//child
10 {
11 printf("this is child.pid:%d ppid:%d\n",getpid(),getppid());
14 char *_argv[]={"ls","-a","-i","-n",NULL};
15 execv("/bin/ls",_argv);
16 printf("child end;\n");
17 }
18 else
19 {
20
21 printf("this is father.pid:%d ppid:%d\n",getpid(),getppid());
22 pid_t ret=waitpid(id,NULL,0);
23 if(ret>0)
24 printf("wait success!ret:%d\n",ret);
25 }
26
27
28 }
结果和上面两个是一样的,就不截屏了。
execle函数:
先创建一个mybin.c
其内容为:
1 #include <unistd.h>
2 #include <stdio.h>
3 extern char** environ;
4 int main(void)
5 {
6 printf("hello pid=%d\n", getpid());
7 int i;
8 for (i=0; environ[i]!=NULL; ++i)
9 {
10 printf("%s\n", environ[i]);
11 }
12 return 0;
13 }
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main()
6 {
7
8 pid_t id=fork();
9 if(id==0)//child
10 {
11 printf("this is child.pid:%d ppid:%d\n",getpid(),getppid());
16 char* _env[]={"MYENV=/a/b/c",NULL};
17 sleep(5);
18 execle("./mybin","mybin",NULL,_env);
19 printf("child end;\n");
20 }
21 else
22 {
23
24 printf("this is father.pid:%d ppid:%d\n",getpid(),getppid());
25 pid_t ret=waitpid(id,NULL,0);
26 if(ret>0)
27 printf("wait success!ret:%d\n",ret);
28 }
结果为:
execve函数:
先创建一个文件mybin.c,内容同上。
myexec.c内容:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int main()
6 {
7 pid_t id=fork();
8 if(id==0)//child
9 {
10 printf("this is child.pid:%d ppid:%d\n",getpid(),getppid());
15 char* _argv[]={"mybin",NULL};
16 char* _env[]={"MYENV=/a/b/c",NULL};
18 execve("./mybin",_argv,_env);
19 printf("child end;\n");
20 }
21 else
22 {
23 printf("this is father.pid:%d ppid:%d\n",getpid(),getppid());
24 pid_t ret=waitpid(id,NULL,0);
25 if(ret>0)
26 printf("wait success!ret:%d\n",ret);
27 }
28 }
结果如下: