Linux学习笔记---009
Linux之进程程序替换理解
前言:
前篇开始进行了解学习Linux的fork函数、进城终止以及进城等待等相关知识内容,接下来学习Linux的进程替换,关于exec*函数族的知识,深入地了解这个强大的开源操作系统。
/知识点汇总/
1、进程程序替换
头文件:
#include <unistd.h>
exec*函数族:(…表示可变参数)
1.int execl(const char* path,const char* arg, …);
2.int execlp(const char* file,const char* arg, …);
3.int execle(const char* path,const char* arg, … ,char* const envp[]);
4.int execv(const char* path,char* const argv[]);
5.int execvp(const char* file,char* const argv[]);
6.int execvpe(const char* file,char* const argv[],char* const envp[]);
1.1、先看代码和现象
#include <unistd.h>
#include <stdio.h>
int main() {
printf("这是原程序的代码\n");
execl("/bin/ls", "ls", "-l", (char *)NULL);
printf("这行代码不会被执行\n");
return 0;
}
根据程序现象可知:
利用exec(新的.exe可执行程序)来替换,当前的进程代码和数据.但是仍然是该进程,只是改变的代码和数据,并不创建新的进程。
即:老进程的壳子,执行新程序的内容。 — 进程替换技术
在Linux环境中,execl系列函数(包括execl、execlp、execle、execv、execvp和execvpe)是用来执行新的程序的。这些函数替换当前进程的映像为新的程序文件,并从该程序的main函数开始执行。一旦execl或其他exec函数被调用成功,原程序的剩余代码将不会被执行,因为原程序的内存映像已经被新的程序替换了。
换句话说,execl函数会导致当前进程停止执行,并被新的程序取代。新程序从它的main函数开始执行,并且与原程序没有直接的关联。因此,原程序中execl调用之后的任何代码都不会被执行。
1.2、替换的原理
进程 = 内核数据结构 + 代码和数据(此时在这步执行代码的进程替换,用新的程序覆盖掉,并不创建新的进程)
站在被替换的进程角度:本质就是这个程序被加载到内存了。
怎么加载?
exec函数可理解于Linux上的加载函数。 – 即程序替换
此类exec函数不关心返回值,因为exec*函数只要替换成功,就不会向后继续执行了;只要继续运行原代码了,一定是替换失败了。
1.3、回顾fork函数的应用
利用fork创建子进程,让子进程自己去替换
测试代码:
创建子进程,让子进程完成任务:
1.之前知识能,让子进程执行父进程代码的一部分
2.现在的exec技术,让子进程执行一个全新的程序。
2、使用所有的替换方法,并且认识函数参数的含义
2.1、exec*函数族
exec函数族:(…表示可变参数)
1.int execl(const char path,const char* arg, …);
2.int execlp(const char* file,const char* arg, …);
3.int execle(const char* path,const char* arg, … ,char* const envp[]);
4.int execv(const char* path,char* const argv[]);
5.int execvp(const char* file,char* const argv[]);
6.int execvpe(const char* file,char* const argv[],char* const envp[]);
以int execl(const char path,const char arg, …);为例**
l: list列表
path: 表示参数需要带路径,意思通过路径找到被替换的程序。
argv[]: 可理解为命令行参数的形式。命令列表。
…: 可变参数
p:用户可以不传文件的path,只需要传文件名(file)即可。
e:环境变量
注意:
a、如果是自定义的环境变量就是整体替换。
b、本质就是,查找这个程序,系统会自动在环境变量PATH中进行查找。
c、所以只要是可执行程序,即进程,那么都可以被替换。
抽象的理解参数就是:你要执行谁(path),你想要怎么执行(命令行参数argv[])
测试代码:
int execv(const char* path,char* const argv[]);
int execlp(const char* file,const char* arg, …);
int execvp(const char* file,char* const argv[]);
…
2.2、exec替换自定义的程序
我们都是替换的系统命令,能否替换自定义的程序呢?
可以,任何语言(c++/java/python/shell…)编写的可执行程序都可以。
测试代码:
测试代码:
int execle(const char* path,const char* arg, … ,char* const envp[]);
int execvpe(const char* file,char* const argv[],char* const envp[]);
小结:
所以我们就能实现环境变量的三种使用方法:
1.子进程中自定义环境变量;
2.继承老的环境变量给子进程,通过全局的environ
3.老的环境变量进行修改,如putenv()函数,新增环境变量
int putenv(char* string);
测试代码:
int putenv(char* string);
3、进程的替换的execve系统调用函数
exec*函数族属于3号手册,不属于2号手册的系统调用.
man 3 exec
只有一个属于系统调用:execve
int execve(const char* filename,char* const argv[],char* const
envp[]);
扩展的exec*函数族底层都是使用的它,扩展出来主要是为了支持不同的使用或应用场景的需求。