替换原理
在Linux中,进程的程序替换(Process Program Replacement)是指一个正在运行的进程使用exec函数族系统调用来加载并执行另一个程序的过程。这个新程序将替换掉原先正在执行的程序,成为该进程的新执行体,且会继承原先进程的一些属性,比如进程PID等。注意exec表示的是一个函数族,linux并没有这个函数,一共有 6 个:
进程=PCB+代码段+数据段
进程替换就是PCB信息基本保持不变,代码段和数据段被新程序替换。包括PID和PPID,在我们看来,程序被替换后可能执行完全不同的程序,这是我们程序员能直接感受到的。但是对于操作系统来说,它只认PID。只要PID没有变,那么就认为这个进程还是原来的进程。
这样做的好处是,可以在不创建新进程的情况下,动态地改变一个进程的执行代码和环境,从而实现程序的动态加载和替换。
可以理解为夺舍?
我们常用子进程去执行另一个完全不同于父进程的程序。例如我们的bash进程执行命令。本来作为bash的子进程,代码和数据都是基本一致的,但是根据实际需求,子进程需要执行指令,也就需要将指令程序替换进来。
观察以下发生程序替换的例子:
exec函数族
有七种以exec开头的函数,可以实现进程的程序替换。
#include <unistd.h>` int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ...,char *const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[],char *const envp[]); int execve(const char *path, char *const argv[], char *const envp[]);
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。 如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值。
以上函数功能相似,在不用的场景下选择合适的函数。
解释函数名
exec函数族中函数带 p(比如execlp、execvp)的表示会自动搜索环境变量PATH.类似的函数名出现以下字符都表示特定的意义:l(list):表示参数采用列表。
v(vector):表示参数用数组。
e(env) : 表示自己维护环境变量
解释参数
path表示的是可执行文件的路径
arg表示命令行参数的某个元素。第一个必须是程序名,其余每一个arg参数表示一条选项用逗号隔开。最后以NULL结尾(具体用法看上面例子)。
file表示可执行文件名,在execvp、execlp中会在其环境变量中去找。
enp[]表示环境变量数组,可提供给替换程序作为环境变量
argv[]表示命令行参数数组,以命令名为首,以NULL结尾。给替换程序提供命令选项。
事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve,所以execve在man手册 第2节(系统调用),其它函数在man手册第3节(库函数)。
这些函数之间的关系如下图所示: