[Linux] Linux 进程程序替换
标题:[Linux] Linux 进程程序替换
个人主页@水墨不写bug
(图片来源于网络)
目录
O、前言
一、进程程序替换的直观现象(什么是进程程序替换?)
二、进程程序替换的原理
三、进程程序替换的函数(怎么使用进程程序替换?)
1.execl
2.execlp
3.execle
1.execv
2.execvp
3.execve
四、进程程序替换的实际应用场景(程序替换的意义?)
进程替换的常见场景:
正文开始:
O、前言
在之前,我们已经学习了什么是进程的创建,退出,等待,以及有关进程地址空间的问题。接下来的进程程序替换依然是属于进程控制的范畴,但是在实际应用中,是非常重要的一种技术。
本文不直接像书本上一样,一开始就说一大堆概念,让人摸不清头脑,而是现观察进程程序替换的现象,然后再从现象中在进一步了解进程程序替换。
一、进程程序替换的直观现象(什么是进程程序替换?)
进程程序替换有一些专门(对口)的函数,我们可以通过man手册查到其中的一个函数:

接下来我们直接看一段代码,用一用这个函数:
#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin...\n");execl("/usr/bin/ls","ls","-a","-l",NULL);printf("process end...\n");return 0;
}
两个打印语句分别标识进程开始与结束,话不多说,直接开始运行,结果如下:

我们惊奇的发现,执行的现象与使用ls的现象差不多!
通过进一步观察,可以发现:
1)在调用execl函数之前的代码(打印process begin 的语句)执行了;
2)调用execl函数就好像使用了 “ls” 命令;
3)调用execl函数之后的代码没有被执行。
为什么会发生这样的情况呢?别急,这就需要深入了解调用execl函数这一动作背后到底发生了什么——于是,我们需要谈一谈进程替换的原理。
二、进程程序替换的原理
我们知道,我们写好并编译好的文件是一个 独立的 可执行程序:
包括我们自己写的mytest,或者是系统上已经装好的ls等指令,都是一个独立的可执行程序。
execl 这类函数的功能就是,把一个新的独立的可执行程序覆盖式的加载到原来的运行起来的进程中,从而实现程序替换。

一个进程,包括内核数据结构 + 代码和数据;这里的程序替换,替换的不仅仅是数据,还要替换代码!这也就意味着原来的代码和数据就被覆盖了,于是进程会从执行execl函数这一行开始,直接执行新加载的代码和数据。原来的数据自然就丢失了:这也就解释了 执行 execl 就像执行力 ls指令 ,在最后执行结束之后并没有打印 “process end” 的原因:
1)执行execl之后,ls的代码和数据被加载的内存中,覆盖替换了原来的代码和数据;
2)原来的 打印 “process end” 的代码由于被覆盖而丢失,所以没有执行;
3)最终的返回值是ls指令的返回值,而不再是原来被覆盖的进程的返回值。
三、进程程序替换的函数(怎么使用进程程序替换?)
我们可以通过进程程序替换的函数名称来略知一二,但是在那样通过函数名称来快速记忆之前,我们还是需要先一个一个了解进程程序替换的函数们:
list(初始化列类型):
1.execl
就像我们之前演示的那样,其实就是execl函数使用方法,接下来需要对这个函数的传参细节做一些深入理解:

参数列表:
*pathname: 需要替换的可执行程序的位置,需要指明具体的位置,既可以使用绝对路径,也可以使用相对路径。
(比如想要替换ls命令,ls命令本质是一个可执行程序,位于/usr/bin/ls,于是我们第一个参数需要这样传递:“/usr/bin/ls”)
*arg: 需要替换的可执行程序的名称
(需要替换的ls命令的名称就是ls,于是需要传递:“ls”)
... : 参数列表
(类似于printf的参数列表不限制打印的参数的个数一样,我们在命令行上想要使用不同的命令,传递的参数的个数是不同的,于是通过参数列表,我们可以传递不同的参数个数,来达到正确执行不同指令的目的)
比如下面的这一个实例就很好的体现了上述的规则:
实例一:
makefile:
当我们想要一次生成多个目标文件,那么可以定义一个伪目标:all
在伪目标后面 + “ : ”+ “ 需要的依赖文件名称 ”
在下文表明生成依赖文件的依赖方法即可:
.PHONY:all all:mytest mmtestmmtest:mytest.ccg++ -o $@ $^ mytest:pra_exec.cgcc -o $@ $^.PHONY:clean clean:rm -r mytest mmtestpra_exec.c:
#include<stdio.h> #include<unistd.h>int main() {printf("process begin...\n");execl("/usr/bin/ls","ls","-a","-l",NULL);printf("process end...\n");return 0; }mytest.cc
#include<iostream> #include<unistd.h> using namespace std;int main() {cout<<"C++进程开始运行"<<endl;execl("./mytest","./mytest",NULL);cout<<"C++进程结束运行"<<endl;return 0; }
由于我们已经编写了makefile,所以只需要make,就可以生成两个可执行程序。
运行结果:
在进程运行的过程中,我们发现进行了两次进程程序替换:
./mmytest (C++程序) ---> ./mytest(C程序) ---> /usr/bin/ls (系统命令C程序)
我们可以通过观察打印信息来观察。
到这里我们可以得出结论:
execl可以替换任何语言的可执行程序。(包括java,python,shell脚本语言等),唯一不同的是通过execl调用的时候传递的参数不同。
接下来的介绍只给出具体函数的使用实例,不再重复介绍同样性质的参数。
2.execlp
#include <unistd.h>
int main()
{// 带p的,可以使用环境变量PATH,无需写全路径execlp("ps", "ps", "-ef", NULL);exit(0);
}
3.execle
#include <unistd.h>
int main()
{char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};// 带e的,需要自己组装环境变量execle("ps", "ps", "-ef", NULL, envp);exit(0);
}
vector(数组类型):
1.execv
#include <unistd.h>
int main()
{char *const argv[] = {"ps", "-ef", NULL};//带v的需要传入数组形式的参数列表 execv("/bin/ps", argv);exit(0);
}
2.execvp
#include <unistd.h>
int main()
{char *const argv[] = {"ps", "-ef", NULL};// 带p的,可以使用环境变量PATH,无需写全路径execvp("ps", argv);exit(0);
}
3.execve
#include <unistd.h>
int main()
{char *const argv[] = {"ps", "-ef", NULL};char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};// 带e的,需要自己组装环境变量execve("/bin/ps", argv, envp);exit(0);
}
函数解释
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。 如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值。 命名理解 这些函数原型看起来很容易混,但只要掌握了规律就很好记。 l(list) : 表示参数采用列表 v(vector) : 参数用数组 p(path) : 有p自动搜索环境变量PATHe(env) : 表示自己维护环境变量

exec*函数簇函数之间的关系:
本质上,这些exec*函数都是对execve函数的封装,为什么?
因为execve是一个系统调用函数!!本质上底层调用的都是相同的形式调用的execve,只不过是上层的封装转换的参数传递的方式。
四、进程程序替换的实际应用场景(程序替换的意义?)
在我们的项目中,我们的父进程一直是运行的,不能说父进程执行了想要执行ls命令,在执行了之后自己却退出了。所以,我们在一般情况下,一定不能让父进程发生程序替换,不然父进程的代码和数据被子进程替换之后,代码和数据就丢失了!
所以我们需要fork创建子进程,让子进程来代替父进程来执行exec*这一类的函数,让子进程来发生程序替换,让子进程的代码和数据被替换掉,这样父进程就可以保留!
进程替换的常见场景:
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
完~
未经作者同意禁止转载
相关文章:
[Linux] Linux 进程程序替换
标题:[Linux] Linux 进程程序替换 个人主页水墨不写bug (图片来源于网络) 目录 O、前言 一、进程程序替换的直观现象(什么是进程程序替换?) 二、进程程序替换的原理 三、进程程序替换的函数(…...
【Linux系统编程】第三十一弹---深入理解静态库:从零开始制作与高效使用的完全指南
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、静态库 1.1、怎么做静态库 1.2、怎么使用静态库 1、静态库 1.1、怎么做静态库 在Linux环境下,通常使用GCC&am…...
FFmpeg 简介及其下载安装步骤
目录 一、FFmpeg 简介 二、FFmpeg 安装步骤 2.1 打开官网 2.2 选择FFmpeg系统版本 2.3 下载FFmpeg压缩包 2.4 将下载好的压缩包进行解压 2.5 设置环境变量 2.5.1 在搜索栏中搜索【环境变量】,然后单击将其打开 2.5.2 找到系统变量中的【Path】,点…...
使用CSS+SVG实现加载动画
使用CSSSVG实现加载动画 效果展示 CSS知识点 SVG元素使用SVG相关CSS属性运用 整体页面布局 <section><div class"box"><div class"loader"><svg><circle cx"40" cy"40" r"40"></circl…...
物联网(IoT)的未来发展:智能互联时代的到来
物联网(IoT)的未来发展:智能互联时代的到来 物联网(IoT)正在迅速改变我们与世界互动的方式。无论是智能家居、智慧城市,还是工业自动化,物联网技术通过设备互联、数据采集和智能控制࿰…...
斯坦福 CS229 I 机器学习 I 构建大型语言模型 (LLMs)
1. Pretraining -> GPT3 1.1. Task & loss 1.1.1. 训练 LLMs 时的关键点 对于 LLMs 的训练来说,Architecture(架构)、Training algorithm/loss(训练算法/损失函数)、Data(数据)、Evalu…...
Java->排序
目录 一、排序 1.概念 2.常见的排序算法 二、常见排序算法的实现 1.插入排序 1.1直接插入排序 1.2希尔排序(缩小增量法) 1.3直接插入排序和希尔排序的耗时比较 2.选择排序 2.1直接选择排序 2.2堆排序 2.3直接选择排序与堆排序的耗时比较 3.交换排序 3.1冒泡排序…...
linux 大小写转换
var"TM_card_INFo" # 把变量中的第一个字符换成大写 echo ${var^} # 把变量中的所有小写字母,全部替换为大写 echo ${var^^} # 把变量中的第一个字符换成小写 echo ${var,} # 把变量中的所有大写字母,全部替换为小写 echo ${var,,} 参考…...
Linux——传输层协议
目录 一再谈端口号 1端口号范围划分 2两个问题 3理解进程与端口号的关系 二UDP协议 1格式 2特点 3进一步理解 3.1关于UDP报头 3.2关于报文 4基于UDP的应用层协议 三TCP协议 1格式 2TCP基本通信 2.1关于可靠性 2.2TCP通信模式 3超时重传 4连接管理 4.1建立…...
centos系列,yum部署jenkins2.479.1,2024年长期支持版本
centos系列,yum部署jenkins2.479.1,2024年长期支持版本 0、介绍 注意:jenkins建议安装LTS长期支持版本,而不是安装每周更新版本,jenkins安装指定版本 openjdk官网下载 Index of /jenkins/redhat-stable/ | 清华大学开…...
正则表达式-“三剑客”(grep、sed、awk)
1.3正则表达式 正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串,将匹配的子串替换或者从某个串中取出符号某个条件的子串等,在linux中代表自定义的模式模版,linux工具可以用正则表达式过滤文本。Linux…...
数智时代的新航向:The Open Group 2024生态系统架构·可持续发展年度大会邀您共筑AI数字新时代
在全球可持续发展和数字化转型双重驱动下,企业正面临着前所未有的挑战与机遇。如何在激烈的市场竞争中,实现业务增长的同时,履行社会责任,达成可持续发展的目标?The Open Group 2024生态系统架构可持续发展年度大会将于…...
TensorFlow 的核心概念
TensorFlow 是一个开源的机器学习框架,由 Google 开发和维护。它提供了一个强大的工具集,用于构建和训练各种机器学习模型。 TensorFlow 的核心概念是计算图(Computational Graph)。计算图由节点(Nodes)和…...
SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz(动态新增、修改等操作)
SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz(动态新增、修改等操作) 前言数据库脚本创建需要被调度的方法创建相关实体类创建业务层接口创建业务层实现类控制层类测试结果 前言 我这边的SpringBoot的版本为2…...
Matlab详细学习教程 MATLAB使用教程与知识点总结
Matlab语言教程 章节目录 一、Matlab简介与基础操作 二、变量与数据类型 三、矩阵与数组操作 四、基本数学运算与函数 五、图形绘制与数据可视化 六、控制流与逻辑运算 七、脚本与函数编写 八、数据导入与导出 九、Matlab应用实例分析 一、Matlab简介与基础操作 重点内容知识…...
【ELKB】Kibana使用
搭建好ELKB后访问地址:http://localhost:5601 输入账号密码登录以后 左侧导航有home、Analysis、Enterprise search 、Observability、Security、Management home:首页Analysis:工具来分析及可视化数据Enterprise search:企业级搜…...
ChatGPT免费使用:人工智能在现代社会中的作用
随着人工智能技术的不断发展,越来越多的应用程序和工具开始使用GPT作为其语言模型。但是,这些应用程序和工具是否收费?如果是免费的,那么他们是如何盈利的?在本文中,我们将探讨ChatGPT免费使用的背后原理&a…...
腾讯音乐:从 Elasticsearch 到 Apache Doris 内容库升级,统一搜索分析引擎,成本直降 80%
导读: 为满足更严苛数据分析的需求,腾讯音乐借助 Apache Doris 替代了 Elasticsearch 集群,统一了内容库数据平台的内容搜索和分析引擎。并基于 Doris 倒排索引和全文检索的能力,支持了复杂的自定义标签计算,实现秒级查…...
CubeMX的FreeRTOS学习
一、FreeRTOS的介绍 什么是FreeRTOS? Free即免费的,RTOS的全称是Real Time Operating system,中文就是实时操作系统。 注意:RTOS不是指某一个确定的系统,而是指一类的操作系统。比如:us/OS,FreeRTOS&…...
C语言初始:数据类型和变量
、 一.数据类型介绍 人有黄人白人黑人,那么数据呢? 我们大家可以看出谁是黄种人,谁是白种人,谁是黑种人,这是因为他们是类似的。 数据也是有类型的,就譬如整数类型,字符类型,浮点…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...




