文章目录
进程程序替换
进程替换有关函数和指令
函数:execl
头文件:unistd.h
返回值:int类型
①成功:就没有返回值,也用不了返回值
因为成功了execl之后的代码和数据就都被换上来的进程的代码和数据替换了,返回值根本用不出来
②失败:返回-1
参数:
①const char* path:要替换上来的可执行程序的绝对/相对路径
②const char* name:要替换上来的可执行程序的名字
③~n:要替换上来的可执行程序的选项
最后一个参数必须以nullptr结尾
参数3其实就是命令行参数中的数组argv中的元素
要替换上来的可执行程序在命令行如何执行[即:命令行参数argv数组的元素,最后必须以nullptr结尾]
作用:把执行这个函数的进程替换成指定路径的进程
函数:execv
头文件:unistd.h
返回值:int类型
①成功:就没有返回值,也用不了返回值
因为成功了execl之后的代码和数据就都被换上来的进程的代码和数据替换了,返回值根本用不出来
②失败:返回-1
参数:
①const char*path:要替换上来的可执行程序的绝对/相对路径
②char* const argv[]:就是把execl中的可变参数[第2个参数到第n个参数]先放进指针数组中,再传给函数
参数2其实就是命令行参数中的数组argv
作用:把执行这个函数的进程替换成指定路径的进程
execl和execv的区别
所以exec之后带v的就表示用数组把选项装起来再传给函数
带l的就表示直接把选项一个一个地传给函数
函数:execlp
头文件:unistd.h
返回值:int类型
①成功:就没有返回值,也用不了返回值
因为成功了execl之后的代码和数据就都被换上来的进程的代码和数据替换了,返回值根本用不出来
②失败:返回-1
参数:
①const char*file:要替换上来的可执行文件的文件名
为什么可以不用写绝对路径呢?
这是因为它会自动地拿着文件名,到环境变量PATH的路径集合里面去找
②~n:和execl一样的可变参数
所以带exec之后带p的,就表示不用传绝对路径,能自己去PATH里面找,直接传文件名字即可
函数:execvp
和execlp同理
就是第一个参数为可执行文件名的,第二个参数为选项表
函数:execvpe
头文件:unistd.h
返回值:int类型
①成功:就没有返回值,也用不了返回值
因为成功了execl之后的代码和数据就都被换上来的进程的代码和数据替换了,返回值根本用不出来
②失败:返回-1
参数:
①const char*file:要替换上来的可执行文件的文件名
②char* const argv[]:就是命令行参数中的数组argv
③char*const envp[] :环境变量表
有2种情况
1,直接用父进程的环境变量,那么就可以不使用这个接口(因为替换进程时不会覆盖环境变量)或者直接传environ
2,想给这个新替换上来的进程,一个新的环境变量表
就可以再自定义一个环境变量表,把这个新的环境变量表传进去
这样这个新替换上来的进程的环境变量就是新定义的环境变量表,而不是继承来的
例
把新的程序的代码和数据放入内存中,就是加载这个程序
所以:
execl等接口就相当于把一个程序加载到内存
execl等接口是系统调用的封装
execl等接口之间的关系:
即
除了execve是系统调用之外
其他的execl等接口都是封装了execve这个系统调用的函数
进程替换的原理
进程替换时,替换上来的进程会把原进程的代码和数据覆盖掉
[默认不会覆盖环境变量,除非使用的替换函数是execvpe
],顺便改页表的映射,栈区,堆区,全局区也会覆盖
但是原进程的PCB等内核数据结构不变
所以进程替换并非
创建了一个新进程
因为
进程=内核数据结构+代码和数据,进程替换只替换了代码和数据,以及修改了替换代码和数据带来的影响
为什么进程替换时,原进程的环境变量不会被覆盖?
shell的环境变量是从操作系统的配置文件里面读取出来的
shell再把读取出来的信息分析之后,再放入shell内部的全局的指针数组中
我们在命令行上执行的命令都是shell的子进程
绝大部分都是shell创建的子进程使用进程替换,搞出来的
而shell使用的进程替换函数是execvpe
shell就通过execvpe把自己全局的环境变量表传给所有子进程
execvpe会把环境变量和命令行参数存放在子进程的特定区域(用户环境区)在进程替换时这一部分区域的数据就不会被替换
就真正完成了环境变量的全局化
所以:
因为自从shell使用execvpe把自己的环境
变量给子进程后,execvpe会把这个环境
变量表放在进程的特定区域(用户环境区)
再
以后,shell的子进程再创建子进程时,就
知道哪些是环境变量了,就会把环境变量放进子进程的用户环境区
而程序再替换时,默认是不会覆盖用户环境区的
进程替换具体会造成什么影响
①代码和数据被替换
②进程地址空间大部分都会被覆盖(环境变量表默认保留,除非使用的是execvpe
)
③信号处理(Signal Handlers):
被忽略的信号(如 SIG_IGN):保持忽略状态。
自定义信号处理函数:会被重置为默认行为(如 SIG_DFL),因为原处理函数的代码已被替换,无法继续执行。
信号屏蔽字(Signal Mask):
子进程的信号屏蔽字(通过 sigprocmask 设置的阻塞信号集合)保持不变
。
④替换之前设置的定时器也会清空
shell的本质
就是先让用户输入命令,然后shell把用户的命令分解
再使用fork创建子进程,再把分解后的命令传给execl等接口,把对应的程序加载到内存,进行执行