【Linux从入门到精通】进程的控制(进程替换)

本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助
文章目录
一、进程替换概念
二、进程替换函数
2、1 execl
2、2 execlp
2、3 execv
2、3 execle
2、4 execve
三、总结
🙋♂️ 作者:@Ggggggtm 🙋♂️
👀 专栏:Linux从入门到精通 👀
💥 标题:进程控制💥
❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️
一、进程替换概念
我们知道,fork() 创建子进程,子进程的代码和数据是和父进程共享一份的。当对任意一个进程修改时,就会发生写时拷贝。当时我们就想让子进程执行一份全新的代码呢?那我们可以使用进程替换。
程序替换就是使用一个接口来实现的。把磁盘上的可执行程序加载到进程的地址空间上。可结合下图理解:
进程替换就是把磁盘上的可执行程序加载到了内存中已经在运行的进程中,加载上的新程序会与原来的进程的页表构成新的映射关系,实际上并没有创建新的进程。
二、进程替换函数
2、1 execl
我们先来看一下execl()函数怎么使用,如下图:
第一个参数是指你所要替换程序的路径。后面的参数是要怎么执行该程序,是一个可变参数列表,但是最后一个参数必须为空。具体使用如下:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { printf("hello linux\n"); execl("/usr/bin/ls","ls","-l",NULL); printf("hello linux\n"); exit(111); return 0; }我们看如下运行结果:
确实执行了ls -l 的命令,但是并没有往下接着执行打印和退出!!!怎么没有打印呢?execl是程序替换,调用该函数后,会将当前的进程所有代码和数据进行替换。所以一旦调用成功,后续的代码将不会在被执行。
exec()系列函数在成功时不会返回,只有在发生错误时才会返回-1。这是因为当exec()函数成功地加载新的可执行程序后,它会在当前进程上下文中完全替换掉当前进程的映像,包括代码、数据、堆栈等。这使得原先的进程状态被新的可执行程序取代,所以在成功加载新程序后,旧程序不再存在,也就无法进行返回操作了。
2、2 execlp
execlp函数对比execl函数,就是所要替换的程序可以自己不带路径。execlp中的 p 指的意思是环境变量PATH,可以默认去找所要替换的程序路径。代码如下:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { printf("hello linux\n"); //execl("/usr/bin/ls","ls","-l",NULL); execlp("ls","ls","-l","-a",NULL); printf("hello linux\n"); exit(111); return 0; }运行结果如下:
2、3 execv
我们再来看一下execv函数的使用。如下图:
其实对比execl函数不难发现,l 表示list的意思,也就是参数列表一个一个列出来。execv函数中的 v 表示vector,参数列表是一个数组。我们可看如下代码:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> char* const _argv[]={"ls","-l","-a",NULL}; int main() { printf("hello linux\n"); //execl("/usr/bin/ls","ls","-l",NULL); execv("/usr/bin/ls",_argv); printf("hello linux\n"); exit(111); return 0; }运行结果如下:
2、3 execle
我们这里就不再解释execvp了,对比上述讲到很容易理解。直接看execle函数。我们先看execle函数怎么使用:
其实我们也不难发现,对比execl函数,参数列表最后多出来一个指针数组。这个指针数组就是维护的环境变量。为了更好的演示该函数,我们先写一下一个我们自己生成的可执行程序去调用我们另一个自己生成的可执行程序。代码如下:
//“————————————————myexec.c————————————————————”#include<stdio.h> #include<unistd.h> #include<stdlib.h> const char* myflie="/home/gtm/primer/test/test_7_23/mycmd"; int main(int argc,char* argv[],char* env[]) { printf("hello linux\n"); //execl("/usr/bin/ls","ls","-l",NULL); //execlp("ls","ls","-l","-a",NULL); execle(myflie,"mycmd","-a",NULL,env); //execv("/usr/bin/ls",_argv); return 0; } //“————————————————mycmd.c————————————————————” #include <stdio.h> #include <string.h> #include <stdlib.h>// ./mycmd -a/-b/-c... int main(int argc, char *argv[]) {if(argc != 2){printf("can not execute!\n");exit(1);}//MY_105_VAL: 目前并不存在!printf("获取环境变量: hello: %s\n", getenv("hello"));if(strcmp(argv[1], "-a") == 0) { printf("hello a!\n"); } else if(strcmp(argv[1], "-b") == 0) { printf("hello b!\n"); } else{ printf("default!\n"); } return 0; }上述代码是在不同的源文件,上述代码中有所标述。我们想要的就是用myexec去调用mycmd。我们在mycmd中想要获取环境变量 hello 的值,但是哦我们并没有设置。所以环境变量hello的值为null。我们看运行结果:
但是我们要在myexec中设置了hello环境变量,
#include<stdio.h> #include<unistd.h> #include<stdlib.h> const char* myflie="/home/gtm/primer/test/test_7_23/mycmd"; int main(int argc,char* argv[],char* env[]) { printf("hello linux\n"); //execl("/usr/bin/ls","ls","-l",NULL); //execlp("ls","ls","-l","-a",NULL); const char* _env[]={"hello=20230724",NULL}; execle(myflie,"mycmd","-a",NULL,_env); //execv("/usr/bin/ls",_argv); return 0; }我们再来看运行结果:
当然,环境变量hello就可以获取相应的值。
2、4 execve
execve函数是属于系统调用函数。我们上述讲到的,如下图:
都是语言级别的函数,底层封装的都是execve函数。事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve。为什么还要封装呢?直接使用execve多好啊。原因是封装后,我们也可以很直接的感受到,应用的场景变多了。其次是用起来,见名知其意。
三、总结
在C++中,exec()系列函数提供了一种在程序中执行外部命令或可执行文件的方法。这些函数包括:execvp()、execv()、execvpe()、execlp()、execl()、execle()和execve()。
execvp()函数:
- 原型:int execvp(const char *file, char *const argv[]);
- 功能:用于在指定的文件路径中搜索可执行文件,并用指定的参数列表运行该文件。
- 优点:可以直接使用文件名作为参数,而无需提供文件路径。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execv()函数:
- 原型:int execv(const char *path, char *const argv[]);
- 功能:在指定的文件路径中搜索可执行文件并用指定的参数列表运行该文件。
- 优点:需要提供文件路径,因此可以明确指定要执行的文件的位置。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execvpe()函数:
- 原型:int execvpe(const char *file, char *const argv[], char *const envp[]);
- 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
- 优点:除了搜索文件路径外,还可以指定环境变量。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execlp()函数:
- 原型:int execlp(const char *file, const char *arg, ...);
- 功能:在系统的环境变量所指定的路径中搜索可执行文件并用指定的参数列表运行该文件。
- 优点:可以直接使用文件名和参数作为参数,而无需提供文件路径。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execl()函数:
- 原型:int execl(const char *path, const char *arg, ...);
- 功能:在指定的文件路径中搜索可执行文件并用指定的参数列表运行该文件。
- 优点:需要提供文件路径和参数,因此可以明确指定要执行的文件的位置和所需的参数。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execle()函数:
- 原型:int execle(const char *path, const char *arg, ..., char *const envp[]);
- 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
- 优点:除了搜索文件路径外,还可以指定环境变量。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
execve()函数:
- 原型:int execve(const char *filename, char *const argv[], char *const envp[]);
- 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
- 优点:需要提供文件路径和参数,以及环境变量,因此可以明确指定要执行的文件的位置、所需的参数和运行环境。
- 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
exec()系列函数允许程序在运行时调用其他可执行文件,以实现更复杂的功能。这些函数提供了不同的方式来指定可执行文件的路径、传递参数和设置环境变量,根据具体的需求,可以选择合适的函数来使用。请注意,exec()函数族在执行成功后,会将当前进程替换为新的进程,因此之后的代码不会被执行到。
相关文章:
【Linux从入门到精通】进程的控制(进程替换)
本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助 文章目录 一、进程替换概念 二、进程替换函数 2、1 execl 2、2 execlp 2、3 execv 2、3 execle 2、4 execve 三、总结 🙋♂️ 作者:Ggggggtm 🙋♂️ 👀 专栏&…...
rancher平台上强制删除pod服务操作
背景: 在日常paas平台运维工作中需要对rancher平台进行巡检的工作,在巡检时发现在rancher管理界面无法删除异常的pod服务, 处理: 像这样的情况就是k8s集群的pod无法通过默认的方式去删除掉pod服务,这时候只能是手工强制…...
【Docker】Docker的通信安全
Docker的通信安全 前言一、Docker 容器与虚拟机的区别1. 隔离与共享2. 性能与损耗 二、Docker 存在的安全问题1. Docker 自身漏洞2. Docker 源码问题 三、Docker 架构缺陷与安全机制1. 容器之间的局域网攻击2. DDoS 攻击耗尽资源3. 有漏洞的系统调用4. 共享 root 用户权限 四、…...
c# 函数中可选参数太多,想设置最后一个参数,又不想修改前面默认参数
C#中,你可以使用命名参数来指定你想要设置的可选参数,而保留其他参数的默认值不变。通过使用命名参数,你可以根据需要选择要为哪些参数提供值,而无需按照它们在函数签名中的顺序提供参数值。 以下是一个示例,演示如何…...
openvino资料(1)
1、c++ - OpenVino model outputs zeroes - Stack Overflow 2、https://chinait-intel.oss-cn-beijing.aliyuncs.com/OpenVINO/Ubuntu20.04%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%BD%BF%E7%94%A8OpenVINO%E9%83%A8%E7%BD%B2BiSeNetV2%E6%A8%A1%E5%9E%8B.pdf 3、c++ - How to cre...
第71篇:某银行外网打点到内网核心区红队评估复盘
Part1 前言 大家好,我是ABC_123。本期分享一篇ABC_123曾经做的针对一家银行的红队评估项目,持续时间两周,难度非常大,但是最终打到了银行核心业务区,今天就复盘一下全过程,希望红蓝双方都能得到一些启示&a…...
网络安全 Day21-数据库知识
数据库知识 1. 什么是数据库2. 为什么需要数据库(分类不清晰)3. 数据库的种类3.1 关系型数据库3.2 NOSQL 数据库3.3 new sql (国产数据库)分布式数据库3.4 云数据库 4. mysql 关系型数据库5. 安装mariadb6. 为mariadb设置密码7. M…...
python测试开发面试常考题:装饰器
目录 简介 应用 第一类对象 装饰器 描述器descriptor 资料获取方法 简介 Python 装饰器是一个可调用的(函数、方法或类),它获得一个函数对象 func_in 作为输入,并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。 装饰器模式通常用…...
语音同声翻译软件让你不再为语言障碍困扰
从前有一个叫黄俊的小伙子,他有一个大梦想:环游世界!但是,他只会说中文,而去到外国又怎么跟当地人交流呢?为了实现自己的梦想,黄俊开始了寻找能帮他解决问题的捷径。这时,方娜向他介…...
又有一个手艺人震惊了B站用户
飞瓜数据(B站版)【热门视频榜】周榜显示,霸占全站视频流量第一的是来自UP主爱捣鼓的邢志磊发布的作品《我花了半年时间给猫做了个房子》。 视频在一周时间内新增播放1232.2万,新增点赞139.4万。 根据视频详细数据显示,…...
HDFS的设计目标和重要特性
HDFS的设计目标和重要特性 设计目标HDFS重要特性主从架构分块存储机制副本机制namespace元数据管理数据块存储 设计目标 硬件故障(Hardware Failure)是常态,HDFS可能有成百上千的服务器组成,每一个组件都有可能出现故障。因此古见检测和自动快速恢复的H…...
【JMeter】JMeter添加插件
目录 一、前言 二、插件管理器 三、推荐插件 1.Custom Thread Groups (1)Ultmate Thread Group (2)Stepping Thread Group 2.3 Basic Graph 资料获取方法 一、前言 在我们的工作中,我们可以利用一些插件来帮…...
测牛学堂:车载测试面试总结之语音助手相关
车载语音助手的工作原理? 语音助手的工作原理总结下来可以分为4个步骤: 1 通过麦克风采集驾驶员的语音指令 2将语音信号转换为数字信号 3过语音识别技术将语音指令转换为计算机可以理解的指令 4 通过语音合成技术将计算机的回应转换为语音输出 车载…...
Android开发之Fragment动态添加与管理
文章目录 主界面布局资源两个工具Fragment主程序 主界面布局资源 在activity_main.xml中,声明两个按钮备用,再加入一个帧布局,待会儿用来展示Fragment。 <?xml version"1.0" encoding"utf-8"?> <LinearLayo…...
Python爬虫+数据可视化:分析唯品会商品数据
目录 前言数据来源分析1. 明确需求2. 抓包分析:通过浏览器自带工具: 开发者工具 代码实现步骤: 发送请求 -> 获取数据 -> 解析数据 -> 保存数据发送请求解析数据保存数据 数据可视化先读取数据泳衣商品性别占比商品品牌分布占比各大品牌商品售价平均价格各…...
el-tree数据渲染超出省略
el-tree数据渲染超出省略 问题 <el-tree:data"deptOptions":props"defaultProps":expand-on-click-node"false":filter-node-method"filterNode"ref"tree"default-expand-allhighlight-currentnode-click"handleNo…...
若依vue -【 44】
44 服务监控讲解 1 需求 显示CPU、内存、服务器信息、Java虚拟机信息、磁盘状态的信息 2 前端 RuoYi-Vue\ruoyi-ui\src\views\monitor\server\index.vue <script> import { getServer } from "/api/monitor/server";export default {name: "Server&quo…...
React 基础篇(一)
💻 React 基础篇(一)🏠专栏:React 👀个人主页:繁星学编程🍁 🧑个人简介:一个不断提高自我的平凡人🚀 🔊分享方向:目前主攻…...
Bean 的作用域和生命周期
目录 什么是 Bean 的作用域 ?Bean 的六种作用域Spring 的执行流程Bean 的生命周期 什么是 Bean 的作用域 ? Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就表示 Bean 在整个 Spring 中只有⼀份,…...
STP和MTP(第二十二课)
2、如何实现 1)在MSTP网络种,引入了域的概念,称为MST域 2)每一个MST域中包含一个或多个“生成树”称为“实例” 3)每个“实例生成树”都可以绑定vlan,实现vlan数据流的负载分担/负载均衡 4)默认情况下,所有的vlan都属于“实例树0:即:instance 0” 5)不同的“实例…...
3个关键功能解析:USBToolBox如何简化macOS与Windows的USB端口映射难题
3个关键功能解析:USBToolBox如何简化macOS与Windows的USB端口映射难题 【免费下载链接】tool the USBToolBox tool 项目地址: https://gitcode.com/gh_mirrors/too/tool 在Hackintosh和跨平台开发领域,USB端口映射一直是个令人头疼的技术难题。US…...
艾尔登法环帧率解锁终极指南:告别卡顿,畅享丝滑游戏体验
艾尔登法环帧率解锁终极指南:告别卡顿,畅享丝滑游戏体验 【免费下载链接】EldenRingFpsUnlockAndMore A small utility to remove frame rate limit, change FOV, add widescreen support and more for Elden Ring 项目地址: https://gitcode.com/gh_m…...
ParaView时间戳设置全攻略:从基础标注到自定义格式(5.8.0实测)
ParaView时间戳设置全攻略:从基础标注到自定义格式(5.8.0实测) 在科学可视化领域,时间戳不仅是数据演变的见证者,更是研究成果呈现的专业语言。ParaView作为开源可视化工具链的标杆,其时间标注功能在学术论…...
ARM PMU外部接口与性能监控寄存器详解
1. ARM性能监控寄存器外部接口深度解析性能监控单元(PMU)是现代处理器架构中用于硬件性能分析的核心模块,它通过一组可编程计数器实时捕获处理器微架构层面的各类事件。在ARMv8/v9架构中,PMU不仅可以通过系统寄存器访问,还提供了标准化的外部…...
用数字逻辑门复刻柏林钟:从二进制编码到硬件实现
1. 项目概述:用数字电路复刻“柏林钟”作为一个在柏林长大的孩子,我从小就对库达姆大街上的那座“柏林钟”着迷。它不像传统时钟那样用指针或数字告诉你时间,而是通过几排不同颜色的发光方块,以一种近乎艺术的方式呈现时间。这种独…...
极致精简,功能强大的PDF编辑工具
这是一款功能全面的PDF编辑工具 你只需要导入一份PDF格式文件 就可以快速的对它进行插入 批注编辑保护转换等各种操作 而且无需登录 也可以直接使用 在插入选项中可以进行插入文字图片 页面页眉页脚页码文档背景水印视频音频等 在批注选项中可以管理批注隐藏批注 高亮显示 文本…...
2026上半年数据库系统工程师(软考)上午题回忆与解析(非标答版)
本文为考后回忆整理,非官方标准答案,旨在为考后对答案及下半年备考的同学提供参考。题目顺序和表述可能与原卷有出入,欢迎在评论区指正、补充。📊 整体考情分析 刚结束的2026年上半年数据库系统工程师考试,上午题的风格…...
口碑最好的AI论文写作工具推荐(从文献整理到论文成稿全流程)适合全体毕业生
还在为选题方向纠结、文献资料翻找耗时、开题报告无从下手、论文框架反复修改、查重率居高不下、降重过程痛苦不堪,甚至答辩PPT还要临时抱佛脚?作为学术新手、应届生或本科硕士毕业生,面对论文写作的重重关卡,流程复杂、操作门槛高…...
告别坐标点击!用Poco精准定位UI控件,让你的Airtest安卓自动化脚本更稳定
告别坐标点击!用Poco精准定位UI控件,让你的Airtest安卓自动化脚本更稳定每次UI微调就导致脚本大面积失效?分辨率变化让精心编写的自动化测试瞬间崩溃?作为从坐标点击转型到控件识别的实践者,我深刻理解这种挫败感。三年…...
CMSIS-DAP调试器原理与应用:以Elektor mbed interface为例
1. 项目概述:Elektor mbed interface [150554] 是什么?如果你玩过ARM Cortex-M系列的单片机,尤其是NXP LPC800系列,那你可能对“CMSIS-DAP”这个调试器标准不陌生。它是由ARM官方推出的一个开源调试接口标准,最大的好处…...











