Linux 进程替换

一、进程替换

把一个进程替换为另外一个进程。对于进程,如果单纯只看复制或者单纯只看替换,没有太大的意义。将复制和替换结合在一起(fork+exec),就是系统去产生一个全新进程的一种方式。

将复制和替换结合在一起(fork+exec):

先fork,使系统中多出一个进程,默认情况下,fork之后,父进程和子进程的代码都一样,子进程是父进程的一个副本,那么把整个副本替换掉, 不会影响父进程,这样就产生了一个全新的进程。所以说系统中的所有新进程并不是直接创建出来的,而是通过fork+exec先复制再替换产生的。这样做的原因是,fork有一个特点,它会把父进程的信息继承给子进程,然后exec进行替换的时候把需要的信息留下,不需要的信息替换掉就可以了,如果是直接创建一个进程,有些信息需要填充,不像复制把父进程的资源复制了一份给了子进程。

二、exec方法

exec系列替换过程:pcb使用替换以前的,只修改了进程的名字,进程实体更换。

1、exec系列的方法

exec系列有多个方法,多个方法在功能本质上没有区别,只是为了适应在不同情况下更加便于使用,所以参数表示形式略有不同,本质上没有任何区别。

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

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

(3)int execle(const char* path, const char * arg,...,char* const envp[]);

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

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

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

前5个方法是库函数,最后一个方法是系统调用,前5个方法最终都调用了execve去完成的。

参数解释:
*path:新替换的程序的路径名称
*arg:传给新程序主函数的第一个参数,一般为程序的名字
*arg后面:是剩余参数列表,参数个数可变,必须以空指针作为最后一个参数

替换成功没有返回值,替换失败才有返回值,因为替换成功就变成了因为一个进程,没被替换之前的进程就消失了。

【例1】execl的应用举例,以ps替换当前程序为例

代码如下:

编译运行以上代码:

由结果可以看出,ps的pid是6331,程序输出的没有被ps替换之前的main程序的pid也是6331。所以可以得出结论,替换的是进程的实体,在替换之后pid是不发生变化的。替换之后,main程序就没有了。printf("替换失败\n");这一行代码是不会被输出的,因为替换成功之后,当前进程main就会直接消失,系统就将它销毁了,直接将ps装载起来了,将main成功替换为ps之后,会从ps的第一行代码开始执行,我们看到的也就是ps这个程序执行的结果。

【例2】execlp的应用举例,以ps替换当前程序为例

execlp中的p就是path,它相当于环境变量的意思,环境变量中就指定了可执行程序在那个位置存放着。所以使用execlp的时候第一个参数为替换掉当前进程的新进程的名称,不需要写路径,它自己会在环境变量path的相关位置帮我们去寻找。

代码如下:

编译并运行:

这个执行结果和用execl的执行结果没有任何区别,是相同的。只是execlp和execl的形式不同而已,它们的功能是相同的。在不方便加路径的情况下就可以用execlp。

【例3】execle的应用举例,以ps替换当前程序为例

execle和前面execl的区别就是把当前进程的环境变量传给了新进程。

代码如下:

编译并运行:

根据结果可以看出,使用execle和使用execl、execlp的功能是一模一样的,没有任何区别。只有在需要改变环境变量的时候才使用execle。

以上三种方法execl和execlp、execle在传参的时候是将参数一一列举出来,而以下三种方法是将所传的参数放入一个数组中。

【例4】execv的应用举例,以ps替换当前程序为例

execv相比较execl来说,它把传给新进程的参数放到了一个数组里面,然后在使用execv的时候就不需要写传给新进程的参数列表,直接写数组名就好了。

有以下代码:

编译及运行结果:

可以看出运行结果和前面的方法没有任何区别。

【例5】execvp的应用举例,以ps替换当前程序为例

execvp方法的使用是在execv的基础上将execv方法中的第一个参数改为替换掉当前进程的新进程的名称,不需要写路径。

编译并运行:

可以看出运行结果和前面的方法没有任何区别。

【例6】execve的应用举例,以ps替换当前程序为例

execve方法的使用是在execv的基础上给execv方法中加了一个环境变量作参数。

代码如下:

编译并运行:

可以看出运行结果和前面的方法没有任何区别。

【注意】execl、execlp、execle、execv、execvp最终内核看到的都是execve的形式。

使用exec系列方法时根据实际情况选择合适的方法进行使用。

相关推荐
诶尔法Alpha8 分钟前
Linux上使用dify构建RAG
linux·运维·服务器
熬夜苦读学习1 小时前
Linux文件系统
linux·运维·服务器·开发语言·后端
沐千熏1 小时前
Liunx(CentOS-6-x86_64)系统安装MySql(5.6.50)
linux·mysql·centos
荔枝荷包蛋6661 小时前
【网络】高级IO——Reactor版TCP服务器
运维·服务器
GGGGGGGGGGGGGG.2 小时前
hapxory-ACL基础介绍及案例
运维·服务器·网络
黑牛先生2 小时前
【Linux】匿名管道
linux·运维·服务器
流星白龙2 小时前
【Linux】35.封装 UdpSocket(2)
linux·运维·windows
是码农没错了3 小时前
银河麒麟系统安装mysql5.7【亲测可行】
linux·运维·kylin
wzhao1013 小时前
WSL进阶使用指南
linux
风静如云3 小时前
OpenBMC:BmcWeb app.run
linux