本文旨在讲解进程替换的知识!希望读完本文,能使读者对进程替换有更深一步的认识!!好的,废话不多说,干货来了!
进程替换的引进!
为什么要引进进程替换呢?我们创建子进程总不能做和父进程做一样的事情把!子进程也应该能做自己想做的事情吧!就拿我们日常生活中的例子来言:一个父亲经营一家公司,其儿子也不一定非得子承父业来选择和其父亲做一样的事情把。所以这就把进程替换这个概念引了进来!
进程替换的概念!
何谓进程替换呢?进程替换就是子进程不再运行父进程的代码和数据了,而是另起炉灶,选择新的代码和数据来执行!
既然进程替换的概念已经简单的介绍了,那么我们就来见一见进程替换把!
进程替换的实例
多进程的进程替换!
下面通过一个简单的多进程的代码来看一看什么是进程替换!
通过上图我们可以看出结果!子进程开始跑之后,调用了一个execl函数!然后父进程一直在跑!等待子进程的退出!最后通过监视进程窗口看见,子进程跑完了,但是子进程跑的代码是我们日常命令行中的ls命令?这难道进行进程替换么?
也有眼尖的小伙伴发现了,直至子进程退出之后,也没有执行其execl之后的代码!这是为什么?而且进程替换之后也没有创建新的进程!从这点我们可以看出,进程的替换并不会引起新的进程的产生!
那么为什么excel之后的代码就不再执行了呢?这就要从进程替换的原理来讲解了!
所谓的进程替换,本质上只是将子进程的代码和数据块进行了修改,其他的结构 并没有做出修改!那么是如何修改的呢?是从磁盘中获取新的代码和数据块,然后在内存中重新找空间,用于这些新的代码和数据块,然后修改子进程从父进程那边继承过来的页表的信息,简单的进程替换就做完了!
那么知道了原理,那该如何解释是如何进行进程替换的呢?
通过上面的调用execl函数可以看出,首先要找到被替换的可执行程序,然后进行选择如何执行这个程序即可!
要想彻底搞懂进程的替换原理,那么我们就不得不介绍系统提供的进程替换函数了!
进程替换函数讲解
通过上图我们可以看出进程替换有很多,他们都是在第三手册(也就是系统调用),下面我们就来详细介绍其中的一些函数!已经他们的使用方法!
execl
函数原型:
其中exec是这些函数的开头,l可以理解成list的意思,即用list传递参数!
可以看出,有两个参数!根据我们刚才多进程的进程替换的实例中,我们可以看出,其中第一个path就是替换后的程序的路径与文件名! 其中第二个参数就是我们日常在bash命令行中怎么写,就在函数传参怎么写就行!后面的三个点代码此函数是一个可变参数列表!表示参数不固定!但是需要注意的是:最后必须以NULL结尾,表示传参完毕!
execlp
函数原型:
其中exelc中的p代表的是PATH,即系统默认的PATH环境变量,所以第一个参数为file,表明只需要写你要替换的程序的名字即可!其中第二个参数上面execl中相同!
下面来看一下此函数的使用方式!
其中第一个参数,只需要将替换后程序的名字写上去就行,无需再进行声明路径即可!
execv
函数原型:
其中execv中的v代表的是一个数组,用于存放命令的选项!
下面来简单来看一下此函数的使用方式!
其中只需要创建一个函数指针数组即可,将程序的选项写入到argv数组即可!其中警告原因是因为前面没有用const修饰,因为它们指向的都是字符串常量!切记:此数组中的结尾也必须以NULL结尾,表示传递参数结束!
execvp
函数原型:
其中p代表的仍然是默认的环境变量,与execv的差距只是第一个参数传参不必再进行传路径了,只需要传被替换的程序名字即可!
使用就不再累赘了!
execvpe
函数原型:
其中e表示的环境变量!
表示该函数继承其父进程的环境变量,其中第三个参数指的是环境变量参数,可以传递系统自带的environ,或者自己自定义的环境变量的字符串指针数组!
具体使用如下:
只要将其中的参数进行正确的传参即可!其中第一个参数,也可以直接将arg[0]传入,第二个传的就命令行参数,第三个就环境变量参数,可以自己定义,也可以传系统自带的environ!
至此,将部分的exec簇家族的函数讲解一番,其他的函数只需要对照其上述的函数使用方式即可!
扩充:
但是当我们进行查找2号手册的时候,我们还会发现还有一个exel簇函数,它为什么在2号手册,和这些簇函数不同呢?
下面我们看一下2号手册的exec函数!
他为什么处于二号手册呢,这里简单介绍一番,其中位于三号手册的系统调用本质上都是调用的此函数!都是对本函数的封装!这是为什么呢?因为每次进程替换的时候,格式不确定,所以不能仅仅通过此函数来调用,因此就封装了这个函数,产生了位于三号手册的那些exec簇函数!
通过上述的进程替换我们可以看出,进程替换替换的都是bash命令行已经存在的命令,那么是否能够替换成我们自己写的程序呢?答案是肯定的!下面我就来写一个代码替换为我们自己写的C++进程!
Makefile
mytest.cc
运行之后,就可以看到将我们的代码替换成c++运行的代码了!
进程替换中环境变量的变化!
1.在进行进程替换的时候,子进程对应的环境变量,可以直接从父进程那边继承过来! 可以使用export新增导入环境变量观察即可!
2.环境变量被子进程继承下来是一种默认的行为,不受程序替换的影响!(因为程序替换只是简单的替换代码和数据段,然后修改页表中的部分内容,对虚拟地址空间也是直接拷贝过来!)
3.子进程获取环境变量的三种方式
一、直接原封不动的由父进程那边继承过来
二、传递自己定义的环境变量参数!
三、新增传递,即原封不动从父进程继承过来之后,再自己进行putenv()操作即可!
至此,关于进行替换的知识介绍完毕,希望能对读者有一定的收获!