进程程序替换
当一个父进程创建出子进程后,可能为了减少父进程的工作负担,也可能要给子进程分配新的任务,所以就需要进行进程替换,让子进程去做一些事.
替换原理:让子进程调用一种 exec 函数来执行另一个程序,子该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行;由于调用 exec 并不创建新进程,所以调用 exec 前后子进程的 id 并未改变
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 execve(const char *path, char *const argv[], char *const envp[]);
exec 函数的命名规则
l(list) | 表示参数采用列表 |
---|---|
v(vector) | 参数用数组 |
p(path) | 有p自动搜索环境变量PATH |
e(env) | 表示自己维护环境变量 |
函数名中含有
'l'
的表示列举参数,如果我们要调用ls -al
指令,就需要将所有参数通过字符串的形式列举出来,即 arg ="ls","-a","-l",NULL;
函数原型
int execl(const char *path, const char *arg, ...);
案列1: execl 实现 ls -a -l
的功能
需要加路径,否则直接跳过该条语句,替换不成功
运行结果如下,之所以没有颜色,是因为我们没有进行配色
函数名含有字符
'p'
的函数不需要指定路径,exec 函数会通过PATH环境变量在指定的各目录中搜寻可执行文件;如果没有 p 则需要指定路径
例如函数 execlp 是可以不用给出路径的,当然如果有路径也不会出错,函数原型为
int execlp(const char *file, const char *arg, ...);
运行结果为:home/maze/ 目录下的所有文件
如果函数名中含有字符 v
表示参数要使用数组,我们可以把参数写在一个指针数组中,例如上面的 “ls -al” 我们可以定义一个指针数组 char* const agr[] ={“ls”,”-a”,”-l”,NULL};
然后把 agr 这个数组名传入函数作为参数.
例如 execv 函数
int execv(const char *path, char *const argv[]);
char* const Arg[]={"ls","-a","-l",NULL};
execv("/bin/ls",Arg);
函数名的最后一个字符是
'e'
的函数不使用当前环境变量,需要自己组装环境变量
char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
execve("/bin/ps", argv, envp);
函数名 | 参数格式 | 是否写路径 | 是否使用当前环境变量 |
---|---|---|---|
execl | 列表 | 需要用户写路径 | 是 |
execlp | 列表 | 可以不写 | 是 |
execle | 列表 | 需要用户写路径 | 否,自己组装环境变量 |
execv | 数组 | 需要用户写路径 | 是 |
execvp | 数组 | 可以不写 | 是 |
execve | 数组 | 需要用户写路径 | 否,自己组装环境变量 |
#include <unistd.h>
int main(){
char *const argv[] = {"ps", "-ef", NULL};
char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-ef", NULL);
// 带p的,可以使用环境变量PATH,无需写全路径
execlp("ps", "ps", "-ef", NULL);
// 带e的,需要自己组装环境变量
execle("ps", "ps", "-ef", NULL, envp);
execv("/bin/ps", argv);
// 带p的,可以使用环境变量PATH,无需写全路径
execvp("ps", argv);
// 带e的,需要自己组装环境变量
execve("/bin/ps", argv, envp);
exit(0);
}
exec 函数的作用
在一个正在运行的进程内部根据函数所指定的文件名和路径找到可执行的文件,并将进程执行的程序替换为新程序,新程序从 main 处开始执行。其中这里的文件必须是二进制文件或 Linux 下可执行的脚本文件,另外,exec 函数族的函数只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆和栈,其它的没有改变
execv 函数的联系
execve 系统调用,其它五个函数最终都调用 execve