【Linux仓库】进程的“夺舍”与“飞升”:exec 驱动的应用现代化部署流水线

🌟 各位看官好,我是egoist2023!

🌍 Linux == Linux is not Unix !

🚀 今天来学习exec系列的进程程序替换,从"fork"的"克隆"到"exec"的"重生"

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦!

目录

书接上文

进程程序替换

原理

替换操作

理解可变参数

execl函数

execv函数

execlp函数

execvp函数

execvpe函数

系统默认环境变量 

自带环境变量

系统+自带 环境变量 

execle函数 

总结  


书接上文

上文介绍了Linux中进程等待的必要性和实现方法。主要内容包括:

  1. 子进程退出后若父进程不回收会导致僵尸进程和内存泄漏;
  2. wait和waitpid函数的使用方法,重点讲解了如何获取子进程退出状态和信号编号;
  3. 非阻塞等待的实现方式,通过WNOHANG选项让父进程在等待子进程时能同时处理其他任务;
  4. 解释了孤儿进程无法被Ctrl+C终止的原因。文章还通过代码示例演示了如何正确获取子进程退出码和信号,以及父进程如何通过轮询方式非阻塞等待子进程。

进程程序替换

通过上一节的学习,我们掌握了如何使用 wait 和 waitpid 来回收子进程资源,避免僵尸进程的产生,并让父进程能够知晓子进程的结束状态。无论是阻塞还是非阻塞等待,其核心目的都是管理一个已经结束或即将结束的“任务”

然而,我们不禁要思考一个更根本的问题:创建子进程的初衷,难道仅仅是为了让它复制一份父进程的代码,然后执行一模一样的操作吗?显然不是。在绝大多数实际应用中,我们创建子进程主要有两个目的:

  1. 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  2. 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

如何让子进程执行一个全新的程序呢?

子进程有自己的代码,有自己的数据 --> 成为一个真正的独立的进程!

原理

程序替换的过程有没有必要创建新的进程呢? --> 没有必要,为什么呢? --> 通过将代码和数据加载到内存里,覆盖代码和数据段。而pcb、虚拟内存空间、页表不会有太大变化,顶多修改页表的映射关系,因此没必要创建一个新的进程。(打印程序替换前后的pid即可证明)

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

正如上文所述,exec 函数族的核心功能是用一个新的程序替换当前进程的映像。这个功能本身是明确的,但在实际应用时,我们调用新程序的需求却是多变的:命令有时需要带上复杂的参数列表,例如 ls -l -a -i

为了理解exec系列的函数,这里需要先提一嘴可变参数,只有理解了可变参数,才能方便引入接下来的exec系列函数.

替换操作

理解可变参数

可变参数函数是指能够接受数量不确定的参数函数。那又是如何做到接受不确定参数数量的呢?毫无疑问,肯定需要一个"路标"指引它从哪里开始走,要走多少步啊!!!

"路标":就是函数里的第一个固定参数 count。它的最大作用就是告诉函数:“从我后面开始,一共有 count 个参数”。

va_start:根据最后一个固定参数,找到可变参数的起始位置

va_arg: 取出当前位置的一个值;把位置移动到下一个参数那里。

va_end:打扫战场,清理工作。


int execl(const char *pathname, const char *arg, ... /*, (char *) NULL */);
int execlp(const char *file, const char *arg, ... /*, (char *) NULL */);
int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char *const envp[] */);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

理解了可变参数后,讲述进程程序替换的操作:六种以exec开头的函数,统称exec函数。

  • 这些函数如果调⽤成功则加载新的程序从启动代码开始执⾏,不再返回。
  • 如果调⽤出错则返回-1
  • 所以exec函数只有出错的返回值⽽没有成功的返回值

execl函数

 int execl(const char *pathname, const char *arg, ... /*, (char *) NULL */); 

  • 第一个参数是传一个程序,程序也是一个文件,是文件就需要有路径 + 文件名;

  • 第二个参数是要执行程序的程序名称;

  • 第三个参数是可变参数,必须以NULL结尾。

举个梨子:

int main()
{printf("我是一个进程,pid:%d,getpid());sleep(1);int n = execl("/usr/bin/ls","ls","-l","-a","-n",NULL);printf("进程结束:%d\n",n);return 0;
}

可以看到我们的程序确实被替换了,但同时也会发现显示器没有打印 “ 进程结束 : ... ” ,直接结束了。为什么会没有后续的打印了呢?不就是被替换了嘛,进程已经执行另一个程序的代码,原来的代码已经没有了。因此程序替换函数一旦调用成功,后续代码不再执行。(失败返回-1)

那么,我们可不可以替换子进程的代码和数据呢?当然可以,子进程会自己执行一个全新的程序。那么会影响到父进程吗?不会,因为进程之间必须具有独立性啊 ! (可以理解成代码如果要被替换,也要进行写时拷贝,如上图所示.)

execv函数

int execv(const char *pathname, char *const argv[]);

  • 第二个参数是一个指针数组,即是把程序名称+可变参数存放在该数组中,传递给子进程的命令行参数。

举个梨子:

char *const myargv[] =
{(char*)"ls",(char*)"-l",(char*)"-i",(char*)"-n",(char*)"-l",NULL
};char **myargv = &argv[1];
execv(myargv[0],myargv);

在前面章节中,我们清楚main函数也是可以带参数的,其中一个就包含命令行参数表。此时./myexe执行自己的执行流,后半部分传递给子进程,让子进程来执行。 (./myexe不就是我们的bash,后半部分不就是我们的命令+选项吗?)

execlp函数

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

  • 第一个参数指明要执行谁,只需要告诉名字,如指令ls。执行指令的命令,需要让execlp自己在环境变量PATH中寻找指定的程序!

execvp函数

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

execvpe函数

int execvpe(const char *file, char *const argv[], char *const envp[]);

  • 第三个参数是一个指针数组,指向环境变量表。 

那么这是否意味着我们同样能通过程序替换函数获取环境变量的内容。这里通过三种操作来观察。

系统默认环境变量 
extern char **environ;char *const myargv[] = {"mycmd",NULL};
execvpe("./mycmd",myargv,environ);

自带环境变量
char *const myargv[] = {"mycmd",NULL};
char *const myenv[] = {"hello=1234","world=1",NULL}
execvpe("./mycmd",myargv,myenv);

系统+自带 环境变量 
char *my = "hello=123456789";putenv(my);
char *const myargv[]={"mycmd",NULL};
execvpe("./mycmd",myargv,environ);

execle函数 

int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char *const envp[] */); 

execle的参数在上面都有谈及,就不再进行过多赘述。 

总结  

  • l(list) : 表⽰参数采⽤列表
  • v(vector) : 参数⽤数组
  • p(path) : 有p⾃动搜索环境变量PATH
  • e(env) : 表⽰自己维护环境变量

为什么程序替换函数要设计这么多个呢?只有传参形式的不同,满足我们未来不同的应用场景!!!

虽然在上层传参形式有所不同,但每个函数内部实际上都调用了同一个系统调用execve!

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

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

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

相关文章

Reachability Query

题目分析 该代码实现了一个动态集合管理系统,支持三种操作:合并集合、切换元素状态、查询集合中是否- 存在活跃元素。核心数据结构为并查集,结合状态标记数组和计数器。关键数据结构与函数 初始化 fa[N]:并查集父节点数组&#xf…

SSL移动接入方案和移动资源发布

一、SSL VPN概述SSL VPN是一种基于SSL/TLS协议的远程安全接入技术,因其广泛兼容Web浏览器,支持“无客户端”部署,具备易于使用和维护的特点。它通过插件系统支持非Web类TCP/UDP应用,并且支持对用户的访问可以做出限制,…

C++STL---count() 统计容器中特定元素出现次数

在 C 标准库中&#xff0c;count 是一个用于统计容器中特定元素出现次数的函数&#xff0c;定义在 <algorithm> 头文件中。它可以快速计算某个值在容器&#xff08;如数组、vector、list 等&#xff09;中出现的次数&#xff0c;避免手动编写循环计数的麻烦。 一、函数原…

Tesla自动驾驶域控制器(AutoPilot HW)的系统化梳理

目前网络上对Tesla自动驾驶硬件&#xff08;AP1-AP4、HW1.0-HW4.0&#xff09;迭代的相关介绍比较混乱&#xff0c;本文这里进行系统化梳理并澄清&#xff0c;并对一些错误进行更正。1、AutoPilot HW迭代图图1 AutoPilot HWMCU迭代图图2 AutoPilot HW 散热设计迭代图&#xff0…

C 语言:第 20 天笔记:typedef(类型重命名规则、应用场景与实战案例)

C语言&#xff1a;第20天笔记 内容提要 构造类型枚举类型typedef综合案例:斗地主预处理 构造类型&#xff1a;枚举类型 使用建议 如果定义不相干的常量&#xff0c;使用宏定义&#xff08;符号常量&#xff09;&#xff1b;如果需要定义一组相关联的常量&#xff08;如月份011、…

在 vue3 和 vue2 中,v-for 和 v-if 可以一起用吗,区别是什么

在 Vue 2 和 Vue 3 中&#xff0c;v-for 和 v-if 可以一起使用&#xff0c;但两者在处理顺序和推荐用法上存在明显区别&#xff0c;主要体现在优先级和最佳实践上&#xff1a; 1. Vue 2 中的 v-for 与 v-if优先级&#xff1a;v-for 的优先级高于 v-if。 这意味着 Vue 会先循环渲…

Linux-进程相关函数

文章目录Linux-进程相关函数父子进程关系父子进程地址空间getpid函数 获取本进程号getppid函数 获取当前进程的进程的父进程号getpgid函数 获取进程组号示例fork函数 创建进程区分父子进程exit函数 进程退出wait函数 等待子进程退出waitpid函数Linux-进程相关函数 每个进程都由…

数据挖掘 6.1 其他降维方法(不是很重要)

6.1 Other dimensionality reduction methods 6.1 其他降维方法 其他降维方法前言问题答案流形3 降维大纲3.1 线性方法3.2 非线性方法3.2.1 流形学习方法&#xff08;Manifold Learning&#xff09;3.2.2 概率方法&#xff08;Probabilistic Approaches&#xff09;3.2.3 拓扑数…

Unity中的特殊文件夹

一.工程路径获取print(Application.dataPath);只用于游戏开发编辑器模式下&#xff0c;游戏发布后此路径就不存在了二.Resources 资源文件夹//路径获取: //一般不获取 //只能使用Resources相关API进行加载 //如果硬要获取 可以用工程路径拼接print(Application.dataPath "…

Seaborn数据可视化实战:Seaborn高级使用与性能优化教程

Seaborn最佳实践与技巧 学习目标 本课程将深入探讨Seaborn库的高级使用技巧&#xff0c;包括性能优化、常见问题解决方法等&#xff0c;旨在帮助学员掌握如何高效地使用Seaborn进行数据可视化&#xff0c;提升图表的美观度和信息传达效率。 相关知识点 Seaborn最佳实践与技巧 学…

分布式系统与单机系统的优劣势对比

近期有遇到一个本地部署的需求&#xff0c;他们希望用主备方案&#xff0c;这就涉及到了备用系统怎么收费的问题。我们是单机系统&#xff0c;其他友商是分布式系统&#xff0c;那20坐席的手拨需求到底是选单机系统好&#xff0c;还是选分布式系统好呢&#xff1f;了解了两者的…

深度学习:从手写数字识别案例认识pytorch框架

目录 一、PyTorch 核心优势与框架定位 二、实战基础&#xff1a;核心库与数据准备 1. 关键库导入与功能说明 2. MNIST 数据集加载与可视化 &#xff08;1&#xff09;数据集下载与封装 &#xff08;2&#xff09;数据集可视化&#xff08;可选&#xff09; 3. DataLoade…

二分|组合|旋转数组

lc1976dijk min_pathpq. min_wlcr187同lc1823.约瑟夫环class Solution { public:int iceBreakingGame(int num, int target) {int x0;for(int i2;i<num;i){x(xtarget)%i;} return x;} };lc2972计算数组中可移除的子数组数量先找最长递增前缀&#xff0c;再结合递增后缀…

【C语言16天强化训练】从基础入门到进阶:Day 10

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C基础知识知识强化补充、C/C干货分享&学习过程记录 &#x1f349;学习方向&#xff1a;C/C方向学习者…

云计算与云原生技术探索

&#x1f31f; Hello&#xff0c;我是蒋星熠Jaxonic&#xff01; &#x1f308; 在浩瀚无垠的技术宇宙中&#xff0c;我是一名执着的星际旅人&#xff0c;用代码绘制探索的轨迹。 &#x1f680; 每一个算法都是我点燃的推进器&#xff0c;每一行代码都是我航行的星图。 &#x…

STM32之ADC详解

一、ADC概述 ADC&#xff08;模拟量转数字量转换器&#xff09;&#xff0c;在 STM32 开发中&#xff0c;利用 ADC 端口的电压数据&#xff0c;转换为对应的具体数字量数据内容。可通过 ADC 方式获取常用数据内容有&#xff1a; 光敏电阻、电池电量、油箱油量 ADC 转换…

深入理解计算机网络:从基础到应用的全面解析

标题&#xff1a;深入理解计算机网络&#xff1a;从基础到应用的全面解析 引言 计算机网络已经渗透到我们生活的方方面面。从家庭Wi-Fi到全球互联网&#xff0c;我们每天都在通过各种设备进行数据交换。本文将带领你走进计算机网络的世界&#xff0c;深入探讨网络的基础知识、常…

以结构/序列/功能之间的关系重新定义蛋白质语言模型的分类:李明辰博士详解蛋白质语言模型

上海交通大学第三届「AI for Bioengineering 暑期学校」于 2025 年 8 月 8—10 日正式开启。本次暑期学校汇聚了自全球 70 余所高校、 10 余所科研机构及 10 余家行业领军企业的 200 余位青年才俊、科研学者和产业代表&#xff0c;共同聚焦于人工智能&#xff08;AI&#xff09…

【大语言模型 15】因果掩码与注意力掩码实现:深度学习中的信息流控制艺术

【大语言模型 15】因果掩码与注意力掩码实现&#xff1a;深度学习中的信息流控制艺术 关键词&#xff1a;因果掩码、注意力掩码、下三角掩码、Padding掩码、序列建模、GPT解码器、BERT编码器、批量处理优化、自回归语言模型、信息流控制 摘要&#xff1a;在Transformer架构中&a…

大型电动化工程机械设备智能施工试验场的网络设计方案

随着工程机械设备逐步迈向智能化、电动化和无人化&#xff0c;传统施工试验场已经难以满足现代化施工设备的研发、测试和验证需求。为了适应这一趋势&#xff0c;建设一个基于高性能网络架构的大型智能施工试验场成为关键。本文将从网络架构、设备选型和功能实现等方面&#xf…