进程程序替换
替换原理
通过fork创建子进程之后是为了执行程序,子进程往往需要调用一种exec函数用来执行另外一个程序,也就是与父进程不同的程序;当进程调用一种exec函数时,创建的子进程就会将指定的程序加载到内存中,并执行;调用exec并不创建新进程,所以调用exec前后该进程的id并没有变化
程序替换的本质:将指定程序的代码和数据加载到指定位置,并不、覆盖父进程的数据和代码
替换函数
以exec开头的函数有六种,统称exec函数
int execl(const char *path, const char *arg, ...);
l:list,将参数一个个低传入 execl中
首先执行程序,先要找到该程序,然后再执行包括如何执行
path表示该程序所在路径;arg表示如何执行该程序,类似与命令行参数;...表示可变参数列表,最后一个参数必须是NULL
运行结果中,只打印了第一个 printf,第二个并没有打印,为什么呢?
因为 printf也是代码,并且第二个是在替换函数 execl之后的,当替换函数执行完毕后,原代码已经全部被覆盖,开始并执行新的程序代码,所以第二个 printf无法执行
int execlp(const char *file, const char *arg, ...);
p:path,可以自动找到程序所在路径,只需要输入待执行的程序即可
第一个ls代表要执行的程序;第二个ls代表如何执行
int execv(const char *path, char *const argv[]);
v:vector,可以将所有可执行参数放入数组中,统一传递,代替使用可变参数
int execvp(const char *file, char *const argv[]);
直接输入待执行的程序,以及如何执行
到目前为止,一直执行的是系统命令,下面尝试执行自己所写的程序
自己所写的程序:
运行结果:
根据运行结果来看,调用非常地成功;所以可以使用替换函数调用任何语言地程序
int execle(const char *path, const char *arg, ..., char * const envp[]);
e:自定义环境变量
先试试将不加入自定义环境变量
上面便是简单地获取两个系统内的环境变量的方式;接下来如果想要自定义环境变量该如何操作呢???
先介绍一个函数:putenv
添加一个环境变量到系统中environ所指向的环境变量表中
自定义环境变量操作如下:
execle可以获取环境变量,同样地上面几种替换函数也可以获取环境变量,在虚拟地址空间中存在着环境变量参数,子进程可通过地址空间获取环境变量
execle的参数列表与 mian函数的命令行参数非常的相似
main也是函数,也要被调用,也要被传参,而execl就是将程序加载到内存中的;所以程序执行的顺序便是:先加载,再执行
程序替换函数的本质是将程序加载到内存中,加载的工作由Linux exec*加载器来完成
函数解释
- 替换函数如果调用成功则加载新的程序从启动代码开始执行,不再返回
- 如果替换失败,返回-1
- 替换函数,只有失败的返回值,没有成功的返回值