进程程序替换(思维提升重点)

发布时间:2026/8/25 13:15:09

进程程序替换(思维提升重点)
进程程序替换第一部分程序替换的基本原理1.1 什么是程序替换调用 exec 系列接口时当前进程已经有了自己的代码、PCB、地址空间和页表你一定是先有一个进程才能替换程序替换执行时会把目标程序的代码和数据覆盖式地载入到当前进程的代码段和数据段替换之后当前进程就开始执行新程序的代码一句话定义程序替换 用新程序的代码和数据把当前进程的代码和数据覆盖掉。现象举例写一个程序前半部分打印自己的代码逻辑后半部分调用 exec 执行ls——运行后你会发现前半部分是你自己的输出后半部分全变成了ls的执行结果。1.2 替换不创建新进程重点在程序替换的过程中并没有创建新的进程进程还是那个进程PCB 还是那个 PCB地址空间还是那个地址空间只是代码段和数据段里的内容被换成了新程序的验证方法PID在程序替换前打印getpid()在 exec 调用的参数里让目标程序也打印自己的 PID例如让新程序自己getpid()打印。会发现替换前后的 PID 完全一样——这就证明了 exec 没有创建新进程。1.3 替换 vs 创建 的区别对比项进程创建fork程序替换exec进程个数多了一个进程2个进程个数不变还是1个PCB新建一个 PCBPCB 不变代码和数据父子各一份写时拷贝原地覆盖目的让子进程成为新的执行单位让当前进程去执行新程序第二部分exec 函数族7 个接口2.1 总览6 1 7 个接口接口特点说明execll参数以列表形式一个个传execlpl p列表传参 PATH 中查找execlel e列表传参 自定义环境变量execvv参数以**数组指针数组**形式传execvpv p数组传参 PATH 中查找execvpev p e数组传参 PATH 自定义环境变量execve系统调用唯一的系统调用其余 6 个都是它的封装61 的秘密你背 6 个名字时按规律排出来是execl, execlp, execl e, execv, execvp, execvpe——等一下execl eexecle和execvpe都在但为什么感觉少了一个其实不是少了而是execve没有和那 6 个货放在一起它单独出来了。2.2 命名规律l / v / p / e我觉得这样方便我们记忆和使用字母英文含义llist参数用列表形式可变参数...一个传vvector参数用数组指针数组char* argv[]一次传pPATH自动去PATH 环境变量里找可执行程序不用带路径eenviron允许自定义环境变量传入不带 p → 必须写完整路径带 p → 只写程序名自动去 PATH 里找。不带 e → 环境变量用默认的父进程继承下来的带 e → 用你传的环境变量表会覆盖旧的。2.3 execl第一个学会的接口重点#includeunistd.hintexecl(constchar*path,constchar*arg,...);参数详解第一个参数path—— 目标程序的路径 程序名告诉系统我要执行谁后续参数可变参数列表C语言的...—— 命令行参数告诉系统我要怎么执行最后一个参数必须是 NULL作为列表结束的标志哨兵值// 示例让当前进程去执行 ls -a -lexecl(/usr/bin/ls,ls,-a,-l,NULL);// ↑路径程序名 ↑程序名(惯例) ↑参数 ↑参数 ↑NULL结尾// 示例执行我们自己的程序 myprocexecl(./myproc,myproc,hello,world,NULL);注意第一个参数和第二个参数的区别——第一个参数path告诉系统文件在哪加载谁第二个参数arg0是命令行参数列表的第一个按惯例写程序名argv[0]它会成为新进程的 argv[0]2.4 返回值特性只有失败才返回重点这是 exec 系列最反直觉的特性printf(before exec\n);execl(/usr/bin/ls,ls,-l,NULL);printf(after exec\n);// 这行永远不会执行成功时如果替换成功exec 不返回代码已经被替换了回不来了后续代码全部不执行如果替换失败exec 返回-1后续代码继续执行进程还是原来的进程原理exec 成功的那一刻当前进程的代码段已经被新程序覆盖CPU 去执行新程序了原来的代码根本不存在了自然无家可归——所以成功时不需要返回也无法返回。失败时代码没被换才能返回 -1 告诉你出错了。常见面试考点exec 函数只有失败时才有返回值-1成功时没有返回值。2.5 execv数组传参v vectorintexecv(constchar*path,char*constargv[]);参数以指针数组形式一次传不用像 execl 那样列表一个个写char*myargv[]{ls,-a,-l,NULL};// 注意 NULL 结尾execv(/usr/bin/ls,myargv);与 execl 对比效果完全一样只是传参形式不同——l 是列表一个个传v 是数组一次传完。小知识main函数的argc/argv之所以能拿到命令行参数就是因为父进程通过 exec 的参数把命令行参数传了进来——你在命令行输入ls -a -lbash 就会用 exec 把ls,-a,-l传给你的程序。2.6 execvpp PATH 自动查找intexecvp(constchar*file,char*constargv[]);两个变化第一个参数不用带路径了只要写程序名如ls系统自动去PATH 环境变量指定的目录里找这个程序char*myargv[]{ls,-a,-l,NULL};execvp(ls,myargv);// 自动在 PATH 里找到 /usr/bin/ls2.7 execvpev p e 全都要intexecvpe(constchar*file,char*constargv[],char*constenvp[]);v参数用数组传p不带路径去 PATH 找e多了一个envp参数——自定义环境变量表char*myargv[]{myproc,hello,NULL};char*myenvp[]{MYENV100,OTHER200,NULL};// 自定义环境变量表execvpe(myproc,myargv,myenvp);注意execvpe 是 GNU 扩展不是所有系统都有。标准 POSIX 里带 e 的是 execle 和 execve。2.8 execve唯一的系统调用重点考点用 man 手册号来区分execve→man 22 号手册→真正的系统调用其余 6 个execl、execlp、execle、execv、execvp、execvpe→man 33 号手册→ C 语言库函数// execve 系统调用原型intexecve(constchar*filename,char*constargv[],char*constenvp[]);关键结论考试重点Linux 系统里真正执行程序替换的系统调用只有一个——execve。其余 6 个接口都是 C 语言对 execve 的封装方便我们在不同场景下传参带路径/不带路径、列表/数组、带不带环境变量。封装时内部会把各种传参形式统一转化成 execve 需要的样子最终都会调用 execve。推论——环境变量为什么不传也有你调用execl、execvp这类没有 e的接口时看起来没传环境变量但底层最终调 execve 时环境变量是必须要传的所以这些接口内部封装时会自动把默认的环境变量表传进去这个默认表就是 C 语言的全局变量environ指向环境变量表的指针从父进程继承下来fork 时拷贝给子进程第三部分fork exec 经典模式重点3.1 为什么必须 fork exec 配合程序替换是自杀式的——exec 成功当前进程就没了变成新程序。如果你在主进程里直接 exec你的主程序就消失了。所以正确姿势是fork创建一个子进程子进程里调用 exec 做程序替换子进程牺牲自己变成新程序父进程继续干自己的事用 wait/waitpid 等子进程#includeunistd.h#includesys/wait.h#includestdio.hintmain(){pid_tidfork();if(id0){// 子进程执行程序替换execl(/usr/bin/ls,ls,-a,-l,NULL);// 走到这说明 exec 失败了perror(execl);exit(1);}// 父进程等子进程waitpid(id,NULL,0);printf(parent is running, child is replaced\n);return0;}现象父进程打印自己的话子进程变成了ls输出目录列表——父进程完全不受影响。3.2 父进程为什么不受影响写时拷贝这里要用到 fork 的**写时拷贝COW**知识fork 之后父子进程共享同一份代码和数据虚拟地址指向同一块物理内存谁要写才发生拷贝子进程 exec 时要覆盖代码和数据 → 触发写时拷贝 → 子进程拷贝出自己独立的一份然后在新拷贝上覆盖新程序父进程的代码和数据原封不动继续正常运行结论程序替换发生时代码和数据都会发生写时拷贝子进程与父进程彻底分离。这正是进程独立性的体现——进程之间互不干扰子进程想怎么折腾包括把自己整个换掉都影响不了父进程。3.3 fork exec 的本质意义为什么要创建子进程为什么 fork 要配合 exec因为多进程编程的最终目的就是让每个进程去执行不同的程序让子进程去跑别的程序干活。如果子进程只能执行和父进程一模一样的代码那多进程就失去意义了。fork exec 创建子进程 让子进程执行全新程序这才是完整的多进程编程模型。第四部分加载器Loader概念4.1 加载器是什么程序加载的本质是动态创建进程的过程。谁负责加载——加载器。exec 就相当于一种加载器把磁盘上的程序文件加载进内存替换当前进程的代码和数据。4.2 bash 就是一个加载器经典例子你在终端敲下ls -a -l回车bash 干了什么bash 是当前进程它fork出一个子进程子进程exec执行lsbash父进程用wait等待ls结束ls结束后bash 继续接受下一条命令所以你运行的所有程序都是 bash 的子进程命令行参数就是 bash 通过 exec 传给子进程的。Windows 类比Windows 下也有类似的 exec 接口。你在 VS2022 里运行程序时VS 就是你的父进程——它帮你 fork 创建子进程再用 exec 加载你的代码把你的命令行参数通过 execv 传进来。第五部分跨语言替换重点5.1 C 程序能替换执行任何语言的程序exec 的目标程序不限于可执行二进制文件可以是另一个 C 程序 ✅C 程序 ✅Python 脚本 ✅PHP 脚本 ✅Shell 脚本 ✅……任何能转化为进程的程序// 示例C 程序替换执行 Python 脚本execl(/usr/bin/python3,python3,mytest.py,NULL);// 示例C 程序替换执行 Shell 脚本execl(/bin/bash,bash,mytest.sh,NULL);5.2 原理真正执行的是解释器以 Python 脚本为例脚本本身不是可执行代码但解释器python3是可执行的exec 加载的其实是解释器程序python3解释器再去读脚本文件解释执行从进程角度看exec 依然是把解释器的代码和数据覆盖进来结论程序替换的程序是一个广义概念——任何能作为一个进程跑起来的程序都可以被替换执行不一定非得是同一种语言编译出来的。第六部分命令行参数传递v 接口的底层理解6.1 参数谁来传你写的程序运行时命令行参数argv和环境变量都是从哪来的答案父进程通过 exec 传的。你的程序是 bash 的子进程你在命令行输入的命令和参数就是 bash 通过 exec 的参数传进来的exec 底层会把命令行参数直接传进新程序的进程新程序的 main 函数才能收到 argv6.2 命令行参数和环境变量的存储命令行参数和环境变量存储在进程地址空间的独立内存区栈的上方/地址空间的高地址区域也是两个独立的区域fork 时这份内存区拷贝给子进程exec 时exec 的参数argv、envp会重新构建这片区域传给新程序第七部分总结各exec参数记忆7.1 代码例子// 1. execl —— 列表传参必须带路径execl(/usr/bin/ls,ls,-a,-l,NULL);// 2. execlp —— 列表传参PATH 查找execlp(ls,ls,-a,-l,NULL);// 3. execv —— 数组传参必须带路径char*argv[]{ls,-a,-l,NULL};execv(/usr/bin/ls,argv);// 4. execvp —— 数组传参PATH 查找execvp(ls,argv);// 5. execvpe —— 数组 PATH 自定义环境变量char*envp[]{MYENV100,NULL};execvpe(ls,argv,envp);// 6. fork exec 经典模式pid_tidfork();if(id0){execl(/usr/bin/ls,ls,-l,NULL);// 子进程替换exit(1);// 走到这 exec 失败}waitpid(id,NULL,0);// 父进程等待本篇总结程序替换exec解决的核心问题让一个进程去执行一个全新的程序且不创建新进程——把目标程序的代码和数据覆盖式载入当前进程的代码段和数据段。exec 函数族共 7 个接口只有 execve 是系统调用其余 6 个是库函数封装只有失败才返回 -1。实际使用中永远配合 forkfork 出子进程 → 子进程 exec 替换 → 父进程 wait 等待父进程靠写时拷贝保持独立性。环境变量传递遵循不传用 environ、传了全覆盖的规则增量新增用 putenv 补齐整表再传。下一篇自定义 shell 设计。

相关新闻

零基础入门python21:Flask账本的数据模型——用户、分类和账目

零基础入门python21:Flask账本的数据模型——用户、分类和账目

2026/8/25 13:05:09

零基础入门python21:Flask账本的数据模型——用户、分类和账目一、上一篇课后练习讲解 上一篇要求使用环境变量并验证测试配置。参考测试通过 create_app({TESTING: True, SQLALCHEMY_DATABASE_URI: sqlite:///:memory:}) 创建临时应用,再在应用上下文中…

Agent Router 一个免费用codex,claude的网站如何接入 CC Switch

Agent Router 一个免费用codex,claude的网站如何接入 CC Switch

2026/8/25 13:05:09

先登录 Agent Router 打开 Agent Router,按页面提供的方式完成登录。登录后进入控制台,左侧通常可以看到数据看板、API 令牌、使用日志、钱包和个人设置等入口 创建 API Key 进入左侧的“API 令牌”,点击“添加令牌”。名称取一个自己能认出…

电商美工PS培训零基础怎么学 ?学设计就业推荐橡果教育

电商美工PS培训零基础怎么学 ?学设计就业推荐橡果教育

2026/8/25 13:05:09

电商美工PS培训零基础怎么学 ?学设计就业推荐橡果教育 当下电商行业持续火爆,淘宝、拼多多、京东、抖音、小红书、跨境电商等平台商家数量逐年递增,市场对电商美工的需求始终处于紧缺状态。不管是品牌旗舰店、直播带货团队,还是中…

具身智能跨本体学习之Open X-Embodiment详解:让22种机器人共享同一套操作经验

具身智能跨本体学习之Open X-Embodiment详解:让22种机器人共享同一套操作经验

2026/8/25 13:55:11

写在前面 【从零走向AGI】旨在深入了解通用人工智能(AGI)的发展路径,从最基础的概念起,逐步构建完整的知识体系。 项目地址🔗:https://github.com/AI-mzq/From-Zero-to-AGI.git 魔方AI空间 猫先生 从零走向…

基于SpringBoot的养生健康平台系统设计与实现源码+文档

基于SpringBoot的养生健康平台系统设计与实现源码+文档

2026/8/25 13:55:11

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

只可读不可改!PDF禁止修改实操方法

只可读不可改!PDF禁止修改实操方法

2026/8/25 13:55:11

在日常办公中,合同、方案、报表、公示等很多文件都是以PDF格式分发。虽然PDF本身版式稳定,但如果没有做权限设置,依旧可以编辑或修改文件。想要防止PDF文件被修改,我们可以用两种方法来设置保护,下面一起来看看具体如何…

HarmonyOS 性能优化工具链:从「手工排查」到「工程化治理」的全栈实战指南

HarmonyOS 性能优化工具链:从「手工排查」到「工程化治理」的全栈实战指南

2026/8/25 13:55:11

文章目录 每日一句正能量摘要一、为什么需要「工具链」思维?二、性能优化工具链全景地图三、开发阶段:在编码期消灭性能缺陷3.1 DevEco Studio Profiler:一站式性能分析面板3.2 ArkTS Linter:编码期的性能守门员3.3 实时预览 Prev…

Meta|Faiss 源码静态审阅:向量检索系统选型前,技术负责人该验证什么?

Meta|Faiss 源码静态审阅:向量检索系统选型前,技术负责人该验证什么?

2026/8/25 13:55:11

Meta|Faiss 源码静态审阅:向量检索系统选型前,技术负责人该验证什么?本文基于固定源码快照 920a631851cc7fefe0645c9af81071bb7b2c1237 进行只读静态审阅。 未执行构建、测试、Benchmark、依赖安装和漏洞扫描。文中所有结论仅代表…

【2015-02-27】centos修改ssh端口

【2015-02-27】centos修改ssh端口

2026/8/25 13:45:11

[历史归档] 本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。 发布时间: 2015-02-27 | 标题:centos修改ssh端口 | 分类: 操作系统 / linux | 标签&#xf…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/24 19:53:32

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/24 19:56:07

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

2026/8/25 0:04:34

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

2026/8/25 0:04:35

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

2026/8/25 0:04:35

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: https:/…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…