朋友们、伙计们,我们又见面了,本期来给大家解读一下有关Linux程序替换的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux

目录
1. 程序替换
我们创建的所有子进程,执行的代码都是父进程代码的一部分!那么如果我们想让子进程执行新的程序呢?执行全新的代码和访问全新的数据,不再和父进程有所瓜葛,那么就需要用到程序替换。
这么多程序替换的函数调用,到底该怎么样用呢?我们直接开始使用:
2. 单进程的程序替换
为了便于理解,我们先从单进程的程序替换开始:
int execl(const char *path, const char *arg, ...);先来看最简单的程序替换接口,其中里面的三个点表示的意思就是可变参数,使用的方法和我们的printf函数中的可变参数一样;
我们程序要能运行起来,第一步先要找到这个程序,第二部如何运行。
- const char* path表示:新程序的文件路径 + 文件名;
- const char *arg表示:这个程序怎么运行(简单的说我们在命令行怎么输就怎么写,最终以NULL结尾)。
返回值:成功没有返回值,失败返回-1。
我们先来演示一遍:让ls命令替换掉我们写的可执行
#include <stdio.h> #include <unistd.h> int main() { printf("pid: %d, exec command begin\n", getpid()); sleep(3); // 程序替换 execl("/usr/bin/ls", "ls", "-a", "-l", NULL); printf("pid: %d, exec command begin\n", getpid()); return 0; }
通过结果可以发现,我们通过execl成功完成了程序替换,但是代码中的最后一行代码为什么没有打印出来呢?这个到后续再解释!
2.1 单进程程序替换的原理
我们已经完成了单进程的程序替换,那么它的原理是什么呢?
当一个进程运行起来时,OS会为它创建PCB、虚拟地址空间、页表,将它的代码、数据加载到物理内存中,并且然后通过页表建立起虚拟到物理的映射关系;当进行程序替换时,execl就将要替换的程序代码和数据直接在物理内存中替换覆盖掉,此时原来的代码和数据就会被新替换的代码和数据覆盖掉,继续向后执行也就执行的新程序的代码和数据,这个过程中并没有创建新的进程。
3. 多进程的程序替换
见识过单进程的程序替换以及程序替换的原理,接下来替换一下多进程:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { pid_t id = fork(); if(id == 0) { // child printf("pid: %d, exec command begin\n", getpid()); sleep(3); // 程序替换 execl("/usr/bin/ls", "ls", "-a", "-l", NULL); printf("pid: %d, exec command begin\n", getpid()); } // parent pid_t rid = waitpid(id, NULL, 0); if(rid == id) { printf("wait success, rid: %d\n", rid); } return 0; }
3.1 多进程程序替换原理
首先,进程具有独立性,其次我们都知道,父子进程代码共享,数据以写时拷贝的方式各自私有一份,那么在程序替换的时候,把子进程的数据替换这没问题,因为父子数据各自私有,但是将代码替换,这就有点不能忍了,父子进程代码共享,既然子进程都执行的是替换后的代码,为什么父进程在程序替换的时候还是继续执行他自己代码呢?
是因为在多进程的程序替换时,当子进程启动程序替换覆盖它们的共享代码时,也会发生写时拷贝的方式,重新开辟一块空间,然后进行替换写入,这样父子进程的代码就不共享,子进程继续执行它替换后的代码,父进程继续执行自己的代码。
在替换完之后,子进程怎么知道从新程序的哪里开始执行呢?
我们的代码在编译形成可执行程序的时候会有一个程序入口地址--entry地址;
CPU内部的eip寄存器可以记录我们程序当前运行到哪里了,所以当程序替换之后,新程序的eip程序计数器就被修改为entry地址,所以就可以重新开始运行了。
接下来解决上面遗留的问题: 代码中的最后一行代码为什么没有打印出来呢?
是因为在程序替换以后,代码和数据都被覆盖了,所以execl函数替换成功后,后续的代码没有机会执行了,因为已经被替换掉了!
所以我们不用判断它的返回值,如果继续执行了后续代码,说明程序替换出错了。</





最低0.47元/天 解锁文章
3118

被折叠的 条评论
为什么被折叠?



