【进程替换】多进程程序替换原理 | 进程程序替换函数 | execlexecv | execlpexecvp

目录

多进程程序替换

多进程程序替换原理

进程程序替换函数详解

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     //child14     sleep(2);15     execl("/usr/bin/ls","ls","-l","-a",NULL);                                                            16     exit(1);17   }18   //father19   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     //child14     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     //child14     sleep(2);15     char *const argv[] =16     {17       (char*)"ls",18       (char*)"-l",                                                                                       19       (char*)"-a",20       (char*)"--color",21       NULL22     };23     execv("/usr/bin/ls",argv); //❗24     exit(1);25   }26   //father27   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     //child14     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     //child14     sleep(2);15     char *const argv[] =16     {17       (char*)"ls",18       (char*)"-l",                                                                                       19       (char*)"-a",20       (char*)"--color",21       NULL22     };23     execvp("ls",argv); //❗24     exit(1);25   }26   //father27   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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/685899.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并发问题系统学习(更新中)

进程、线程 进程&#xff1a;进程是代码在数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位。可以理解为一个java应用。 线程&#xff1a;线程是进程的一个执行路径&#xff0c;一个进程中至少有一个线程&#xff0c;进程中的多个线程共享进程的资源。…

2024.05.10作业

TCP服务器 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; …

Paddle 基于ANN(全连接神经网络)的GAN(生成对抗网络)实现

什么是GAN GAN是生成对抗网络&#xff0c;将会根据一个随机向量&#xff0c;实现数据的生成&#xff08;如生成手写数字、生成文本等&#xff09;。 GAN的训练过程中&#xff0c;需要有一个生成器G和一个鉴别器D. 生成器用于生成数据&#xff0c;鉴定器用于鉴定数据的准确性&…

国产开源物联网操作系统

软件介绍 RT-Thread是一个开源、中立、社区化发展的物联网操作系统&#xff0c;采用C语言编写&#xff0c;具有易移植的特性。该项目提供完整版和Nano版以满足不同设备的资源需求。 功能特点 1.内核层 RT-Thread内核包括多线程调度、信号量、邮箱、消息队列、内存管理、定时器…

[c++]多态的分析

多态详细解读 多态的概念多态的构成条件 接口继承和实现继承: 多态的原理:动态绑定和静态绑定 多继承中的虚函数表 多态的概念 -通俗的来说&#xff1a;当不同的对象去完成某同一行为时&#xff0c;会产生不同的状态。 多态的构成条件 必须通过基类的指针或者引用调用虚函数1虚…

合并两个有序链表(C语言)———链表经典算法题

题目描述​​​​​​21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09;&#xff1a; 答案展示: 迭代&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* mergeTwoLis…

【docker 】push 镜像到私服

查看镜像 docker images把这个hello-world 推送到私服 docker push hello-world:latest 报错了。不能推送。需要标记镜像 标记Docker镜像 docker tag hello-world:latest 192.168.2.1:5000/hello-world:latest 将Docker镜像推送到私服 docker push 192.168.2.1:5000/hello…

【吃透Java手写】2-Spring(下)-AOP-事务及传播原理

【吃透Java手写】Spring&#xff08;下&#xff09;AOP-事务及传播原理 6 AOP模拟实现6.1 AOP工作流程6.2 定义dao接口与实现类6.3 初始化后逻辑6.4 原生Spring的方法6.4.1 实现类6.4.2 定义通知类&#xff0c;定义切入点表达式、配置切面6.4.3 在配置类中进行Spring注解包扫描…

python中如何把list变成字符串

python中如何把list变成字符串&#xff1f;方法如下&#xff1a; python中list可以直接转字符串&#xff0c;例如&#xff1a; data ["hello", "world"] print(data1:,str(data)) 得到结果&#xff1a; (data1:, "[hello, world]") 这里将整个…

芋道----工作流中添加邮件通知

1、配置邮件发送的账号 2、编辑邮件的内容模板 如何新建邮箱&#xff0c;直接查看芋道官网即可&#xff0c;已经讲解的很详细了&#xff0c;可以直接点击下方链接 邮件配置 | ruoyi-vue-pro 开发指南 (iocoder.cn)https://doc.iocoder.cn/mail/#_3-1-%E6%96%B0%E5%BB%BA%E9%82…

Android项目转为鸿蒙,真就这么简单?

最近做了一个有关Android转换成鸿蒙的项目。经不少开发者的反馈&#xff1b;许多公司的业务都增加了鸿蒙板块。 对此想分享一下这个项目转换的流程结构&#xff0c;希望能够给大家在工作中带来一些帮助。转换流程示意图如下&#xff1a; 下面我就给大家介绍&#xff0c;Android…

26、Qt使用QFontDatabase类加载ttf文件更改图标颜色

一、图标下载 iconfont-阿里巴巴矢量图标库 点击上面的链接&#xff0c;在打开的网页中搜索自己要使用的图标&#xff0c;如&#xff1a;最大化 找到一个自己想用图标&#xff0c;选择“添加入库” 点击“购物车”图标 能看到刚才添加的图标&#xff0c;点击“下载代码”(需要…