【进程替换】多进程程序替换&原理 | 进程程序替换函数 | execl&execv | execlp&execvp

目录

多进程程序替换

多进程程序替换原理

进程程序替换函数详解

execl&execv

execlp&execvp

execle&execvpe 

execve


多进程程序替换

  • 我们想要进程替换的同时不影响旧的进程(使用多进程版)
  • fork创建子进程,让子进程去替换执行新程序(因为替换进程本身不会创建新的进程)
  • 父进程依旧执行旧的进程,且等待子进程(非阻塞等待)
  • 父进程只等待子进程(阻塞等待)
  • 子进程可以替换系统指令,也可以替换我们自己的程序,只要是一个可执行程序都可以替换。
  • 两全其美:既让子进程完成了任务,又不能让父进程受到影响

说明fork创建子进程完成任务:

  • 让子进程执行父进程代码的一部分
  • 让子进程执行一个全新的程序
  • 基于进程间的独立性原则。
  • fork创建的子进程默认在不修改的前提下,父子进程的数据和代码时共享的。
  • 子进程发生了进程替换,相当于发生写入,发生了写时拷贝。
  • 执行一个全新的程序,父子进程是独立的,所以不仅数据要写时拷贝,代码也要发生写时拷贝。只要程序替换成功了,父子进程无论是代码/数据在内核数据结构层面上,数据代码层面上彻底分开了。

子进程发生程序替换:

  • 共享父进程的数据代码
  • 暂停了把新程序的代码和数据从磁盘到内存的加载/写入
  • 发生写时拷贝
  • 开启加载/写入(页表的权限会改变)
  • 重新建立映射关系
 1: testexec.c 
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 
  7 int main()
  8 {
  9   printf("testexec.... begin!\n");
 10   pid_t id = fork();
 11   if(id == 0)
 12   {
 13     //child
 14     sleep(2);
 15     execl("/usr/bin/ls","ls","-l","-a",NULL);                                                            
 16     exit(1);
 17   }
 18   //father
 19   int status = 0;
 20   pid_t rid = waitpid(id,&status,0);
 21   if(rid > 0)
 22   {
 23     printf("father wait success!,child exit code: %d\n",WEXITSTATUS(status));
 24   }
 25   printf("testexec... end!\n");
 26   return 0;
 27 }

//测试失败
execl("/usr/bin/lsss","lsss","-l","-a",NULL);    

【测试成功】细看退出码

【测试失败】细看退出码

 

多进程程序替换原理

  • 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)
  • 子进程往往要调用一种exec函数以执行另一个程序。
  • 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换。
  • 从新程序的启动,程开始执行。
  • 调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

进程程序替换函数详解

前篇粗略的介绍了下替换函数,现在一个一个详解介绍。使用所有的替换方法,并且认识函数参数的含义

  • OS中默认进程程序替换函数有6个库函数和1个系统调用函数。
  • 其实有六种以exec开头的函数,统称exec函数
#include <unistd.h>`
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);

int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
//系统调用函数
int execve(const char *path, char *const argv[], char *const envp[]);

execl&execv

  • l:list列表
  • int execl(const char *path, const char *arg, ...); 
  • path:表示替换程序的路径(绝对/相对路径均可)☞☞怎样找到可执行程序需告知
  • arg:可变参数,在命令行中怎么执行,就怎么传参。☞☞你想怎么执行
  • arg形成命令行参数表传给ls指令的可执行程序main函数接收使用
  • 注意❗最后必须以NULL结尾

  • V:Vector动态数组
  • int execv(const char *path, char *const argv[ ]);
  • path:表示替换程序的路径(绝对/相对路径均可)☞☞怎样找到可执行程序需告知
  • argv:指针数组(可变参数与其一个一个传参,直接放到数组里面,传数组即可)(带入命令行参数表)
  • argv被当作命令行参数表传给ls指令的可执行程序main函数接收使用
  • 字符串的类型是const char*变成char*需要强转
  • 注意❗最后必须以NULL结尾
  • 这两个函数只是在传参形式上发生了变化,实际上没有区别。
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 
  7 int main()
  8 {
  9   printf("testexec.... begin!\n");
 10   pid_t id = fork();
 11   if(id == 0)
 12   {
 13     //child
 14     sleep(2);
 15     execl("/usr/bin/ls","ls","-l","-a",NULL);  //❗                                                          
 16     exit(1);
 17   }


//
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 
  7 int main()
  8 {
  9   printf("testexec.... begin!\n");
 10   pid_t id = fork();
 11   if(id == 0)
 12   {
 13     //child
 14     sleep(2);
 15     char *const argv[] =
 16     {
 17       (char*)"ls",
 18       (char*)"-l",                                                                                       
 19       (char*)"-a",
 20       (char*)"--color",
 21       NULL
 22     };
 23     execv("/usr/bin/ls",argv); //❗
 24     exit(1);
 25   }
 26   //father
 27   int status = 0;
 28   pid_t rid = waitpid(id,&status,0);
 29   if(rid > 0)
 30   {
 31     printf("father wait success!,child exit code: %d\n",WEXITSTATUS(status));
 32   }
 33   printf("testexec... end!\n");
 34   return 0;                                                                                              
 35 }

execlp&execvp

  • p:环境变量PATH
  • 带p的函数不用带绝对/相对路径传递参数了,表示用户可以不传递替换程序的路径(但是要传递可执行程序的文件名file)
  • 用户可以不传递要执行的文件路径(文件名要传),直接告诉exec*,我要执行谁即可。
  • p:查找这个程序,系统会自动在环境变量PATH中进行查找。
  • int execlp(const char *file, const char *arg, ...);
  • int execvp(const char *file, char *const argv[ ]);
 1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 
  7 int main()
  8 {
  9   printf("testexec.... begin!\n");
 10   pid_t id = fork();
 11   if(id == 0)
 12   {
 13     //child
 14     sleep(2);
 15     execlp("ls","ls","-l","-a",NULL);  //❗                                                          
 16     exit(1);
 17   }


//
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 
  7 int main()
  8 {
  9   printf("testexec.... begin!\n");
 10   pid_t id = fork();
 11   if(id == 0)
 12   {
 13     //child
 14     sleep(2);
 15     char *const argv[] =
 16     {
 17       (char*)"ls",
 18       (char*)"-l",                                                                                       
 19       (char*)"-a",
 20       (char*)"--color",
 21       NULL
 22     };
 23     execvp("ls",argv); //❗
 24     exit(1);
 25   }
 26   //father
 27   int status = 0;
 28   pid_t rid = waitpid(id,&status,0);
 29   if(rid > 0)
 30   {
 31     printf("father wait success!,child exit code: %d\n",WEXITSTATUS(status));
 32   }
 33   printf("testexec... end!\n");
 34   return 0;                                                                                              
 35 }

execle&execvpe 

  • e:environment环境变量
  • int execle(const char *path, const char *arg, ...,char *const envp[ ]);
  • int execvpe(const char *file, char *const argv[ ],char *const envp[ ]);

  • bash有环境变量,也可以获取命令行参数
  • bash创建父进程
  • fork创建子进程
  • 通过exec*等函数将环境变量表和命令行参数表交给可执行程序
  • 子进程运行起来,并使用两张表

execve

🙂感谢大家的阅读,若有错误和不足,欢迎指正。 下篇收尾❗

  • 0
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐唐思

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值