exec函数族

exec函数族

  • fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的ID并未改变。
  • exec只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆栈和栈段。
  • 有7种不同的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[]);
int fexecve(int fd, char *const argv[], char *const envp[]);

函数解释

  • 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
  • 如果调用出错,则返回-1.
  • 所有exec函数只有在出错的时候才有返回值,如果成功,则没有返回值。

命名解释

  • 这些函数前4个字母都是一样的,只有后面的几个字母是不一样的,因此我们只要掌握规律就可以很好的掌握它。
    • l(list):表示参数采用列表
    • v(vector):参数用的数组
    • p(path):函数后有p的会自动搜索环境 变量PATH
    • e(env):表示自己维护环境变量
函数名参数格式是否带路径是否使用当前环境变量
execl列表不是
execlp列表
execle列表不是不是,需要自己组装环境变量
execv数组不是
execvp数组
execve数组不是不是,需要自己组装环境变量
execlp函数
  • 加载一个进程,借助PATH环境变量
int execlp(const char *file, const char *arg, ...);		
成功:无返回;失败:-1
  • 参数1:要加载的程序的名字。该函数需要配合PATH环境变量来使用,当PATH中所有目录搜索后没有参数1则出错返回。
  • 该函数通常用来调用系统程序。如:ls、date、cp、cat等命令。
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 int main()
  6 {
  7     pid_t pid;
  8     pid = fork();
  9     if(pid < 0)
 10     {
 11         perror("fork error");
 12         exit(0);
 13     }
 14     else if(pid > 0)
 15     {
 16         sleep(2);
 17         printf("I am parent !\n");
 18     }else
 19     {
 20         execlp("ls","ls","-a","-l",NULL);
 21     }
 22     return 0;
 23 }

在这里插入图片描述

  • execlp(“ls”,“ls”,"-a","-l",NULL);这个函数有一个需要注意的地方,我们看到第二个参数也是“ls”,其实传入给的是argv[0],这个参数在可以任意改动,不会出错,原因是这个参数并不参与函数内部的使用。
execl函数
  • 加载一个进程, 通过 路径+程序名 来加载。
    int execl(const char *path, const char *arg, ...);		
    成功:无返回;失败:-1
  • 对比execlp,如加载"ls"命令带有-l,-F参数
execlp("ls", "ls", "-l", "-F", NULL);	     使用程序名在PATH中搜索。
execl("/bin/ls", "ls", "-l", "-F", NULL);    使用参数1给出的绝对路径搜索。
  • 代码和上面的代码只是换了20行代码。
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 int main()
  6 {
  7     pid_t pid;
  8     pid = fork();
  9     if(pid < 0)
 10     {
 11         perror("fork error");
 12         exit(0);
 13     }
 14     else if(pid > 0)
 15     {
 16         sleep(2);
 17         printf("I am parent !\n");
 18     }else
 19     {
 20         execl("/bin/ls","ls","-a","-l","-h",NULL);
 21     }
 22     return 0;
 23 }

在这里插入图片描述

  • 可以看到效果是一样的
execvp函数
  • 加载一个进程,使用自定义环境变量env
int execvp(const char *file, const char *argv[]);
  • 变参形式:

    • ①…
    • ② argv[] (main函数也是变参函数,形式上等同于
      • int main(int argc, char *argv0, …))
  • 变参终止条件:① NULL结尾 ② 固参指定

  • execvp与execlp参数形式不同,原理一致。

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 int main()
  6 {
  7     pid_t pid;
  8     pid = fork();
  9     if(pid < 0)
 10     {
 11         perror("fork error");
 12         exit(0);
 13     }
 14     else if(pid > 0)
 15     {
 16         sleep(2);
 17         printf("I am parent !\n");
 18     }else
 19     {
 20         char* ergv[] = {"ls","-a","-l","-h",NULL};
 21         execvp("ls",ergv);
 22     }
 23     return 0;
 24 }

在这里插入图片描述

exec函数调用例子
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6     char* const argv[] = {"ps","-ef",NULL};
  7     char* const envp[] = {"PATH=/bin:usr/bin:","TERM=console",NULL};
  8 
  9     execl("/bin/ps","ps","-ef",NULL);
 10 
 11     //带p的,可以使用环境变量,无须写全路径
 12     execlp("ps","ps","-ef",NULL);
 13 
 14     //带e的。需要自己组装环境变量
 15     execle("ps","ps","-ef",NULL,envp);
 16 
 17     execv("/bin/ps",argv);
 18 
 19     //带p的,可以使用环境变量PATH,无须写全路径
 20     execvp("ps",argv);
 21 
 22     //带e的,需要自己组装环境变量
 23     execve("/bin/ps",argv,envp);
 24 
 25     return 0;
 26 }

  • 事实上,只有execve是真正的系统调用,其他的五个函数最终都调用execve,所以execve在man手册上的第2节,其他函数在man手册的第3节。
    在这里插入图片描述
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值