一、理解进程替换
首先,exec* 系列函数能让进程执行新程序,上图我们用到的是 int execl(const char* path, const char* arg, ...)函数,所以相当于执行了 ls -la 指令,这就完成了进程的替换。
本来子进程中存放的是父进程的代码和数据,但是由于进行进程替换,所以要执行的程序会把他的代码和数据进行覆盖。
由于用的还是老进程的内核数据结构,只是覆盖老进程的代码和数据,所以没有创建新进程。
细节
1、本质就是把新程序加载到内存。
2、exec* 系列函数类似于Linux中的加载函数,是系统调用。
3、exec* 系列函数执行完之后原来的代码被替换,exec* 函数也就不关心返回值了,只要替换成功就向下运行,反之向后运行就一定是替换失败。
二、代码的多进程
1、理论
fork() 函数创建子进程,让子进程进行进程替换,父进程不受影响。
子进程有两个任务:
(1)执行父进程的一部分代码(代码不拷贝)
(2)执行一个全新代码(代码拷贝修改)
一开始父子进程指向同一个代码数据,替换代码是把拷贝的代码数据进行覆盖。
我们发现进程替换之后父子进程有各自独立的代码数据和内核数据结构。
2、理解exec* 系列函数
(1)int execl(const char* path, const char* avg, ...)
l:list 列表
path:执行程序要带路径
avg:在命令行中怎么执行就怎么传参,以NULL结尾
...:可变参数
(2)int execv(const char* path, char* const argv[])
v:vector 数组
argv[]:把arg传入数组argv[]
(3)int execlp(const char* file, const char* arg, ...)
p:path 路径
file:可执行程序名
makefile中要一次执行两个程序可以这样写:
(4)int execvpe(const char* file, char* const argv[], char* const envp[])
e:环境变量
envp[]:替换环境变量表
该函数把命令行参数和环境变量传给子进程。
bash 内部有两张表,创建子进程时把表传给他。
所以理解代码:
extern char** environ;
execvpe(....., environ);
代表我是子进程,我把父进程的父进程(bash)传给父进程的环境变量表 environ 传给子进程,作为替换环境变量。
若想在环境变量表中增加,可用以下函数:
这是c库中的函数,系统调用是int execve()函数。