进程替换,exec系列函数使用

14 篇文章 0 订阅
12 篇文章 0 订阅

上一篇文章我们创建子进程的目的:  if else 让子进程执行父进程代码的一部分。

如果我想让子进程执行一个“全新的程序”呢?————这就需要用到进程替换。

1、概念/原理  

进程替换就是指进程不变(进程的pcb,进程地址空间不变),仅仅替换当前进程的代码和数据的技术(新程序的替换旧进程的),叫做进程的程序替换,这样就好像子进程执行了一个全新的程序。

有没有创建新的进程呢?   答案是没有

(1)替换原理

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

程序替换的本质就是把程序的进程代码+数据加载进特定进程的上下文中!

C/C++程序要运行,必须先加载到内存中!

如何加载呢?使用加载器

加载器的底层原理就是使用exec*程序替换函数

(2)子进程调用exec执行程序替换,为什么父进程不受影响?

父子代码难道不是共享的吗?为什么新程序替换了子进程的代码和数据以后,父进程不受影响呢?

        因为进程是具有独立性的,进程程序替换会更改代码区的代码,此时也会发生写时拷贝,拷贝一份代码和数据给子进程,然后再将新程序中的代码和数据替换子进程中的。

(3)exec*返回值

        只要进程的程序替换成功,就不会执行后续代码,意味着exec*函数,成功的时候,不需要返回值检测(exec系列函数执行成功以后,原进程中的代码和数据都会被替换掉,自然也就不会执行exec*后面的代码,exec*自然也就不会返回了;如果exec*返回了,那exec系列函数一定是执行失败了。)

只要exec*返回了,就一定是因为调用失败了!

2、替换函数exec

其实有六种以exec开头的函数,统称exec函数:

#include <unistd.h>

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[]); 

函数解释:

这些函数如果调用成功则加载

新的程序从启动代码开始执行,不再返回。
如果调用出错则返回-1
所以exec函数只有出错的返回值而没有成功的返回值。



命名理解

l(list) : 表示参数采用列表(比如execl)
v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
e(env) : 表示自己维护环境变量(自己定义环境变量替代系统的环境变量)

execl
int execl(const char *path, const char *arg, ...);

l(list) : 表示参数采用列表
第一个参数是path,填的就是你要执行的目标程序的全路径,即所在路径/文件名
第二个参数之后,表示的是可变参数列表,要执行目标程序在命令行上具体该怎么执行,这里参数就需要一个个传递过去(“ls” “-a”  “-l”三个参数,缺一不可),最后必须传入NULL,作为参数传递的结束。

execv
int execv(const char *path, char *const argv[]);

v(vector) : 参数用数组
第一个参数和execl一样,path

第二个参数是一个指针数组,将execl中按照列表形式给出的参数放到这个数组里面。(最后需要加上NULL)

可以理解为它把这个参数数组,直接给了ls命令的main函数中的命令行参数数组argv。

execlp
int execlp(const char *file, const char *arg, ...);

p(path) : 有p自动搜索环境变量PATH
带了l所以是参数是以列表的形式给出

带了p所以第一个参数只需要给出文件名即可,在调用execlp的时候会帮我们根据环境变量PATH帮助我们找这个文件。要注意两个ls的区别,第一个是指定程序/文件名,第二个ls是要在命令行上给出的参数(想要执行ls命令,ls本身也要给出)

execvp
int execvp(const char *file, char *const argv[]);

v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
第一个参数只需要给文件名

第二个参数给参数数组

execve
int execve(const char *path, char *const argv[], char *const envp[]); 

e(env) : 表示自己维护环境变量(自己定义环境变量替代系统的环境变量)
第一个参数给全路径

第二个参数给参数数组

第三个参数表示自己定义一个环境变量,然后传进来,替换系统的环境变量

exec系列函数总结

        这六个函数(加上execvpe一共七个)实际上只是参数上的不同,最终都是调用execve,系统给我们提供的实际上只有这一个接口,其他接口都是在此基础上封装出来的。(通过man手册也可以发现execve在man手册的2区内,表示是系统调用)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值