进程的程序替换,exec 函数族。
fork 创建子进程后执行的是和父进程相同的程序,如果需要他执行不同的代码分支,子进程旺旺需要调用一种 exec 函数以执行另一个程序。当进程调用一种 exec 函数时,该进程的用户空间代码的数据完全被新程序替换,从新程序的启动例程开始执行。调用 exec 并不创建新的进程,所以调用 exec 前后该进程的 id 并未改变。
当前进程的 .text 和 .data 替换为所需要加载的程序的 .text 和 .data,然后让进程从新的 .text 第一条指令开始执行,进程的 id 不变,换核子不换壳子。
exec 函数族的一些参数有些不同,底层实现原理一样。
1 | SYNOPSIS |
- l(list) : 表示参数采用列表
- v(vector) : 参数用数组
- p(path) : 有p自动搜索环境变量PATH
- e(env) : 表示自己维护环境变量
事实上,只有 execve 是真正的系统调用,其他五个函数最终都调用 execve,所以 execve 在 man 手册第 2 节,其他函数在 man 手册的第 3 节。这些函数之间的关系如下图:
execl()
加载一个进程,通过 路径+程序名 来加载。
1 | int execl(const char *path, const char *arg0, ... /*, (char *)0 */); |
返回:成功:无返回;失败:-1。
参数:path:可执行程序的路径,如/bin/ls
。后面跟要传给这个程序的参数。
有了这个函数就可以来加载一个自定义的程序了。
栗子:
1 |
|
execlp()
加载一个进程,借助 PATH 环境变量。
1 | int execlp(const char *file, const char *arg0, ... /*, (char *)0 */); |
返回:成功:没有返回;失败:-1。
参数:file:要加载的程序名。该函数需要配合 PATH 环境变量来使用,当 PATH 中所有目录搜索后没有参数 file 则返回出错。后面跟传给要执行程序的参数。
该函数通常用来调用系统程序。如:ls、date、cp、cat 等。
栗子:
1 |
|
execle()
最后一个参数是一个数组,自己的环境变量数组,这个数组必须以 NULL 结尾。
1 | int execle(const char *path, const char *arg0, ... /*, (char *)0, char *const envp[] */); |
execv()
1 | int execv(const char *path, char *const argv[]); |
栗子:
1 |
|