目录
1、进程替换现象
exec*函数作用:进程代码使用exec*函数,可以执行新的程序
例如下述一个简单的实例:
#include<unistd.h>
#include<iostream>
#include<stdio.h>
int main() {
char *args[] = {"/bin/ls", "-l", nullptr}; // ls -l 命令
execvp(args[0], args); // 执行 ls -l,并替代当前进程
// 如果execvp返回,表明出现了错误
perror("execvp");
return 1;
}
对应的makefile文件:
myprocess:myprocess.c
g++ -o myprocess myprocess.c -std=c++11
.PHNOY:clean
clean:
rm -f myprocess
执行结果:
2、如何理解
进程 = 内核数据结构 + 代码和数据
继承替换的本质是替换代码和数据,而没有修改内核数据结构
这个过程要融合冯诺伊曼体系结构进行理解:
这个过程叫做,进程的程序替换
同时,这个过程并没有创建新的进程
也就是说,用老进程的壳,执行新的代码和数据
而站在别替换程序的角度来说,就是该程序被加载到内存了
所以,exec*函数,可以是视为一种加载函数
把外设的数据搬到内存中
同时,exec*系列的函数,执行完毕后,后续的代码和数据被替换了
excel函数的返回值不关心
只要替换成功,就不会向后继续运行
只要继续运行,就说明替换失败
子进程在进行程序替换时,为了确保独立性
子进程的数据和代码都会发生写时拷贝
3、exe*系列函数
l:list列表
v:vector数组
p:path路径
e:env环境变量
(1)execl
execl(const char *path, const char *arg, ...);
l是list列表
第一个参数path:执行的程序需要带路径,怎么找到程序
第二个参数:命令行中怎么执行,就怎么传参
例如:ls -a - l
替换时:
execl("/usr/bin/ls","ls","-a","-l",NULL);//当参数列表结束,必须一NULL结尾
第一个参数:你想执行谁,路径,解决的是找到的问题
第二个参数:你想怎么执行,解决的是如何解决的问题
(2)execlp
-
execlp(const char *file, const char *arg, ...)
:- 函数原型:
int execlp(const char *file, const char *arg, ...)
- 功能:从系统的路径变量中查找可执行文件并执行。
- 参数:
file
:要执行的程序的名称,不带路径。arg
,...
:可变参数列表,表示要传递给新程序的命令行参数。参数列表必须以NULL
结束。
- 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。
- 函数原型:
(3)execle
-
execle(const char *path, const char *arg, ..., char * const envp[])
:- 函数原型:
int execle(const char *path, const char *arg, ..., char * const envp[])
- 功能:执行指定路径的可执行文件,并指定环境变量。
- 参数:
path
:要执行的程序的路径。arg
,...
:可变参数列表,表示要传递给新程序的命令行参数。参数列表必须以NULL
结束。envp
:环境变量数组,用于设置新程序的环境变量。数组必须以NULL
结束。
- 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。
- 函数原型:
(4)execv
-
execv(const char *path, char *const argv[])
:- 函数原型:
int execv(const char *path, char *const argv[])
- 功能:执行指定路径的可执行文件,通过数组传递命令行参数。
- 参数:
path
:要执行的程序的路径。argv
:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以NULL
结束。
- 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。
- 函数原型:
(5)execvp
-
execvp(const char *file, char *const argv[])
:- 函数原型:
int execvp(const char *file, char *const argv[])
- 功能:从系统的路径变量中查找可执行文件并执行,通过数组传递命令行参数。
- 参数:
file
:要执行的程序的名称,不带路径。argv
:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以NULL
结束。
- 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。
- 函数原型:
(6)execvp
-
execve(const char *path, char *const argv[], char *const envp[])
:- 函数原型:
int execve(const char *path, char *const argv[], char *const envp[])
- 功能:执行指定路径的可执行文件,通过数组传递命令行参数,并指定环境变量。
- 参数:
path
:要执行的程序的路径。argv
:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以NULL
结束。envp
:环境变量数组,用于设置新程序的环境变量。数组必须以NULL
结束。
- 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。
- 函数原型:
4、传环境变量
原来我们说过,bash创建一个子进程的时候
首先bash会有一张命令行参数表和环境变量表
通过某种方式传递给子进程
那么是通过什么方式呢?
就是通过execvpe这个函数
int execvpe(const char *file, char *const argv[], char *const envp[]);
argv就是命令行参数表,envp就是环境变量表
环境变量的参数,如果传的是自定义的,那么就会全部替换为自定义后的环境变量
传环境变量的规则:
1、新的环境变量,自己构建,这样会全部替换bash的环境变量
2、老的环境变量,(bash)extern char** envion
3、putenv(“xxx = xxx”)新增环境变量表,只是新增,而不是全部替换
本质上,7个函数只有execve这个系统调用
其他函数都是这个系统调用的封装