目录
execl
execv
execlp
execvpe
编辑
再认识环境变量:
进程的替换不是创建新进程,用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。exec函数就有一种代替指定进程执行的意思。
下面来讲解原理:
首先2号文件差不多它,所以进程替换函数不是系统调用,是只是 用户态的 C 库函数,由C语言封装的函数。
我们接着看一下是怎么替换进行运行的。
首先exec作为一个进程被加载到操作系统中,然后覆盖待替换的进程的数据段,然后修改原页表的映射关系,使其指向这个exec的进程,所以不是创建一个新的进程而是替换了而已。
execl
我们看一下这个进程替换函数的结构,首先返回值,调用函数如果成功就直接指向替换的那个进程的内容,如果失败就直接返回-1,所以如果成功是看不到返回值的,这点和exit退出函数有点像,成功就没有返回值了。第一个参数是要替换的可执行程序的路径,第二个参数是一个可变参数,可以填写很多,是表示怎么执行,带什么附加指令,但是要以空结尾,相当于链表将一个一个结点链接起来,然后最后置空。如果要替换的是bin目录之下的ls指令,那arg就是ls+选项,这里可以分开写也可以整合起来写。
可以看到这个execl跑去执行人家ls的代码,这里有人就有个疑问,为什么execl可以找到ls的位置并替换它,这里用的是环境变量PATH找到的。
execl可以替换ls还可以替换某些进程的。
比如我们要替代other进程打印其pid我们就可以使用execl锁定路径。
第一个参数是路径,第二个是要运行的对象和怎么运行的。
execv
int execv(const char *path, char *const argv[]);
这个和上面那个差不多,就是将怎么执行全部封装成一个数组再传进去,
这个argv参数和main函数的是一样的,都是由父进程传递的。
main
函数的 argv
是由 操作系统 在程序启动时传递的,具体来说,是 程序启动时的 shell(或父进程)传递的参数。而execv的argv是由命令行传的。
execv的区别和execl在传参形式的区别就好像list和vector的区别。
execlp
这些以p结尾的都可以不带路径传递了,int execlp(const char *file, const char *arg, ...),第一个参数file是传的想替代那个指令或者进程,第二个和execl一样的,运行什么和怎么运行。
咦那以ls为例,不就传了两个“ls”了吗,这里不重复的,第一个ls是程序名,第二个是怎么运行的惯例,execlp是通过环境变量PATH来找到ls的。
execvpe
这个最复杂,第一个参数可以传路径也可以传要执行的程序(可以是可执行文件名,会自动从 PATH
搜索)。第二个参数和前面一样,第三个参数是传递环境变量,可以是自己创建的也可以是系统里面的。execvpe
用来用新的环境变量执行另一个程序,替换当前进程,execvpe
主要是 "让当前进程变成另一个程序,并带上新的环境变量"。就是增加或者替换环境变量。
可以看到替换了所有other打印的环境变量,相当于替换了某个进程的环境变量。
那可不可以添加呀,可以的putenv,环境变量的格式是“xxxx=xxxx”,如下:
然后再通过execl替换执行other就可以了,这个putenv也可以写在父进程里面,或者全局。
再认识环境变量:
1。子进程会继承父进程的全部环境变量
2。程序替换不影响命令行参数和环境变量