一、进程替换
把一个进程替换为另外一个进程。对于进程,如果单纯只看复制或者单纯只看替换,没有太大的意义。将复制和替换结合在一起(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系列方法时根据实际情况选择合适的方法进行使用。