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系列方法时根据实际情况选择合适的方法进行使用。

相关推荐
好哈优学编程26 分钟前
操作系统知识1
运维·系统安全
很透彻27 分钟前
vscode连Linux虚拟机(超简单)
linux·运维·服务器
小嵌同学1 小时前
SPI驱动学习六(SPI_Master驱动程序)
linux·驱动开发·学习·嵌入式·c·spi
¥ 多多¥5 小时前
数据结构:内存的使用
linux·c语言·开发语言·数据结构
咕噜Yuki06095 小时前
博睿谷IT认证-订阅试学习
linux·学习·redhat·rhce·红帽认证·ocm认证
冰红茶兑滴水5 小时前
Linux 线程互斥
linux·c++
King without kingdom6 小时前
面试题(三)
运维·服务器·网络
Sam90296 小时前
828华为云征文|Flexus云服务器X实例部署宝塔运维面板
运维·服务器·华为云
元素之窗7 小时前
如何在 CentOS 中管理用户、组和服务状态
linux·运维·centos
咩咩大主教8 小时前
Linux下的简单TCP客户端和服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·网络编程