linux|Linux--进程程序替换

替换原理
1.当fork创建子进程后,父进程与子进程执行相同的代码,往往子进程要调用exec函数去执行新的程序。(让一个进程去执行一个全新的程序)
2.当进程调用exec,则当前进程的代码和数据全部被替换,堆和栈也要重新分配。
3.调用exec成功没有返回值,失败返回-1.

  • 为什么调用成功没有返回值?
    因为调用exec成功,则当前进程的代码和数据已经被替换,以前的堆和栈已经被销毁,返回值也保存在栈中,栈已经被销毁,则返回值不存在。
如下可以证明没有返回值:
#include #includeint main() { int ret = execl("./hello","./hello",NULL); printf("%d\n",ret); return 0; }

运行结果如下:(发现没有输出ret的值,说明执行成功没有返回值)
linux|Linux--进程程序替换
文章图片

4.调用exec并不创建新进程,所以调用exec前后,进程的pid不变。
替换函数
1.有6种以exec开头的替换函数,统称为exec函数。
#includeint execl(const char* path,const char* arg,...); //后面以NULL结束 int execlp(const char* file,const char* arg,...); int execle(const char* path,const char* grg,...,char* constenvp[]); int execv(const char* path,const char* argv); //argv数组也要以NULL结束 int execvp(const char* file,const char* argv); int execve(const char* path,const char* argv,char* const envp[]); //envp数组也是NULL结束//事实上,只有execve是系统调用,其它函数都调用了execve

2.函数参数
path:表示对应的文件在哪个目录下(也表示我要执行的程序是哪一个);
file:只用填文件名,系统会在PATH下找;
envp[]:表示自己设置的,替换后的程序的环境变量
3.命令理解
l(list):表示参数采用列表形式
v(vector):参数采用数组形式
p(path):有p自动搜索环境变量PATH
e(envp):表示自己设置(维护)环境变量(自己设置的环境变量是什么,则最新程序的环境变量就是什么)
execl
int execl(const char* path,const char* arg,...);

1.示例1:(让进程去执行ls -l命令)
#include #includeint main() { execl("/bin/ls","ls","-l",NULL); return 0; }

运行结果
linux|Linux--进程程序替换
文章图片

对于命令ls -l的运行结果如下:
linux|Linux--进程程序替换
文章图片

可以发现两个运行结果一致,只是通过终端执行的命令里面的字会带颜色(这是权限的问题)。
2.示例2:(让进程去执行./hello程序,./hello是hello.c编译生成的一个可执行程序)
hello.c
#includeint main() { printf("hello world\n"); return 0; }

execl.c
#include #includeint main() { execl("./hello","./hello",NULL); return 0; }

运行结果:
linux|Linux--进程程序替换
文章图片

execv
int execv(const char* path,const char* argv);

1.程序代码
#include #includeint main() { char* argv[] = {"ls","-l",NULL}; execv("/bin/ls",argv); return 0; }

2.运行结果
linux|Linux--进程程序替换
文章图片

注意:argv数组必须以NULL作为结束,否则程序运行就会出现错误,例如下面的程序就是错误的。
#include #includeint main() { char* argv[] = {"ls","-l"}; execv("/bin/ls/",argv); return 0; }

linux|Linux--进程程序替换
文章图片

execlp
int execlp(const char* file,const char* arg,...);

1.程序代码
#include #includeint main() { execlp("ls","ls","-l",NULL); return 0; }

2.运行结果
linux|Linux--进程程序替换
文章图片

execvp
int execvp(const char* file,const char* argv);

1.程序代码:
#include #includeint main() { char* argv[] = {"ls","-l",NULL}; execvp("ls",argv); }

2.运行结果:
linux|Linux--进程程序替换
文章图片

execle
int execle(const char* path,const char* grg,...,char* constenvp[]);

1.程序代码
(1)hello.c(里面通过getenv函数获得AAA环境变量的内容)
#include #includeint main() { printf("AAA=%s\n",getenv("AAA")); printf("hello world\n"); return 0; }

(2)execle.c(envp为自己设置的环境变量的数组,以NULL作为结束标志)
#include #includeint main() { char* envp[] = {"AAA=123",NULL}; execle("./hello","./hello",NULL,envp); return 0; }

2.运行结果
当执行execle.c程序之前,运行hello.c程序,发现AAA的环境变量为NULL,因为不存在。
linux|Linux--进程程序替换
文章图片

执行execle.c,发现hello.c程序里面的环境变量AAA值变成了自己设置的123。
linux|Linux--进程程序替换
文章图片

execve
int execve(const char* path,const char* argv,char* const envp[]);

1.程序代码
#include #includeint main() { char* argv[] = {"./hello",NULL}; char* envp[] = {"AAA=456",NULL}; execve("./hello",argv,envp); return 0; }

【linux|Linux--进程程序替换】2.运行结果
linux|Linux--进程程序替换
文章图片

    推荐阅读