个人主页:Lei宝啊?
愿所有美好如期而遇
目录
当一个进程调用进程替换函数时,该进程的数据和代码完全被新程序的代码和数据所代替,而后重新构建页表的映射关系,进程还是之前的进程,并未创建新的进程。
我们可以用fork创建出子进程,让子进程通过程序替换去执行另一个程序。
我们一个一个进行使用与验证,同时,我们的指令也是程序,运行起来也是进程,所以我们程序替换就以替换指令为例子。
使用execlp,我们就不需要关心路径的问题,因为系统会自动去我们的环境变量PATH下的路径去寻找。
或者我们这样写也可以
?execvp也是同样的道理,我们不用再加路径,不做演示。
最后我们演示一种带e的函数,在演示之前,我们仍然有几个问题就是,既然ls这种系统的程序我们可以执行,那么我们自己的程序可不可以替换执行呢?我们又怎么知道带e的函数有没有传递环境变量表呢?不带e的函数他又能不能传递环境变量表呢?
我们可以看到我们没有传递环境变量表,但是mytest依然得到了环境变量表,这是为什么?我们可以想到进程有进程地址空间,进程地址空间里有环境变量的虚拟地址,父进程创建子进程时,子进程会继承父进程的进程地址空间和页表,而且在程序替换时,仅仅只是局部的替换,替换程序的代码和数据,不会替换环境变量表。
我们也就解答了上面几个问题,我们当然可以替换执行我们自己的程序,同时带或者不带e的函数都是可以传递环境变量表的,而且通常我们使用带e的函数都是因为我们想要一张全新的环境变量表,否则我们不管使用哪一个函数,默认都会继承父进程的环境变量表,其实,这些函数的功能都是相同的,都是进程替换,只是传递的参数不同罢了。
我们上面了解到了子进程会默认继承父进程的环境变量表,也可以是我们自己写的全新的环境变量表,我们还有一种就是在本进程下新增环境变量,使用putenv函数(c99不支持,记得改makefile)。
但是,这并不会影响我们的bash,他只影响本进程及其子进程。
那么我们可以看见的是7个函数,既然功能相同,为什么在慢查询execve函数时不和其他六个函数在一起呢?
进程替换,替换进程的代码和数据,这是由操作系统所管理的,所以他会为用户提供一个进程替换的系统调用,而我们上述的6个函数,全部都封装了这个系统调用。
1、从开始我们就会发现,进程替换成功后,exec系列的函数后面的代码都不会再执行,因为该进程的代码和数据已经被替换了,所以如果执行了后面的代码,就是替换失败,我们直接exit。
2、替换成功后,进程还是之前的进程,不会新创建,我们来验证。
3、创建一个进程,先创建他的PCB,进程地址空间和页表,然后才将他的代码和数据加载进内存,而进程替换的本质工作,就是做进程数据和代码的加载,新建的一个进程,加载代码和数据时本质也就是进程替换,将代码和数据覆盖式的加载到内存上。
4、无论是什么语言,只要能在linux下跑起来,那么我们就可以进行程序替换,也就是说,C语言写的代码可以调用Python、java等等语言的可执行程序,因为在进程替换时,本质就是替换二进制的代码和数据。