版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liu_zhen_kai/article/details/81911364
进程替换
在fork之后,产生的子进程会拥有和父进程相同的代码段和数据段,执行父进程相同的公共代码,但是多数情况下我们不会让子进程做与父进程相同的工作,这样就会用到进程替换的概念。
进程替换可以使用exec函数族来完成替换工作
exec族函数在man手册的资料:
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[]);
进程一旦被替换,则从新的程序main函数开始运行起来,所有的参数列表,环境变量都可以由用户自己定义, 而且被替换成功的进程不会执行原函数下面的代码
在man手册中的五个exec族函数分别代表着不同的用法,可以这样来记忆:
- 当结尾有l (list),代表着需要平铺(也就是每个都输入)所有的新进程中需要用到的命令行参数(也就是main函数的第二个参数argv[ ])以NULL结尾
- 当结尾有p,代表操作系统自动捕获环境变量PATH(路径),则不需要手动输入路径,仅仅输入文件名即可
- 当结尾带有v,则可定义char*型指针数组存放新进程需要的参数列表,传值只传一个char*地址即可
- 当结尾带有e,则可以由用户自己定义其新进程的环境变量(但是这个新的环境变量不会影响系统的环境变量,仅在该进程中使用)
- If any of the exec() functions returns, an error will have occurred. The return value is -1, and errno will be set to indicate the error(替换错误返回-1,正确没有返回值)
下面对每个函数的用法举例
execl() :
1 //example for execl
2
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8
9 int main(void)
10 {
11 int ret;
12 printf("this is the function execl : \n");
13
14 ret = execl("/bin/pwd", "pwd", NULL);//替换到 pwd 命令
15
16 printf("exec failed\n"); // 如果进程运行到这里代表替换失败
17 return 0;
18 }
~
运行结果如下
[liu@localhost ecexl]$ cc execl.c -o execl
[liu@localhost ecexl]$ ./execl
this is the function execl :
/home/liu/boke/03/ecexl
可见运行结果在进程被替换成功,而且进程不会回到原来的代码继续执行,而是在新的程序中直接返回
execlp():
1 //example for execlp
2
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8
9 int main(void)
10 {
11 int ret;
12 printf("this is the function execlp : \n");
13
14 ret = execlp("pwd", "pwd", NULL); //不需要加路径,只需要加文件名
15
16 printf("exec failed]n");
17 return 0;
18 }
运行结果:
[liu@localhost execlp]$ ./execlp
this is the function execlp :
/home/liu/boke/03/execlp
execle():
1 //example for execle
2 //execle.c
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6
7
8 int main(int argc, char* argv[], char* env[])
9 {
10 printf("HOME=%s\n", getenv("HOME"));
11 printf("USER=%s\n", getenv("USER"));
12 //打印系统默认的环境变量
13 char* ENV[] = {"HOME=XI'AN", "USER=LIU"};
14 //给定新的进程环境变量
15 int ret = execle("./tmp", "tmp", NULL,ENV);
16
17 printf("execle failed\n");
18 return 0;
19 }
0//tmp.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4
5
6 int main(int argc, char* argv[], char* env[])
7 {
8 printf("this is function tmp\n");
9 printf("HOME=%s\n", getenv("HOME"));
10 printf("USER=%s\n", getenv("USER"));
11 return 0;
12 }
运行结果
[liu@localhost execle]$ ./tmp
this is function tmp
HOME=/home/liu
USER=liu
[liu@localhost execle]$ ./execle
HOME=/home/liu
USER=liu
this is function tmp
HOME=XI'AN
USER=LIU
被替换时环境变量改变为设置的值,但是直接运行不会改变环境变量
execv():
1 //example for execv
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7
8 int main(void)
9 {
10 char* argv[] = {"ls", "-a", "-l", NULL};
11 printf("this is main function :\n");
12
13 execv("/bin/ls", argv);
14
15 printf("execv error\n");
16 return 0;
17 }
运行结果
[liu@localhost execv]$ ./execv
this is main function :
total 20
drwxrwxr-x. 2 liu liu 4096 Aug 21 10:12 .
drwxrwxr-x. 6 liu liu 4096 Aug 21 10:08 ..
-rwxrwxr-x. 1 liu liu 4836 Aug 21 10:12 execv
-rw-rw-r--. 1 liu liu 245 Aug 21 10:12 execv.c
execvp():
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4
5
6 int main(void)
7 {
8 char *argv[] = {"ls", "-l", NULL};
9
10 execvp("ls", argv);
11
12 printf("execvp error\n");
13 return 0;
14 }
运行结果
[liu@localhost execvp]$ cc execvp.c -o execvp
[liu@localhost execvp]$ ./execvp
total 12
-rwxrwxr-x. 1 liu liu 4802 Aug 21 10:16 execvp
-rw-rw-r--. 1 liu liu 178 Aug 21 10:16 execvp.c