当前位置: 首页 > news >正文

【Linux】进程控制-----进程替换

目录

一、为什么要进行进程替换:

二、进程替换的原理:

三、exec家族:

1、execl:

2、execlp:

3、execv:

4、execvp:

5、execle和execve

​编辑

putenv:


一、为什么要进行进程替换:

当父进程创建子进程之后,这两个进程后面的代码是共享的,但是更多的场景下是给子进程执行分配任务,让子进程执行它自己的任务,这个时候就需要进程替换了,让别的进程替换子进程,但是这个替换并没有创建PCB

程序替换的目的是让子进程帮我们执行特定任务

二、进程替换的原理:

单进程替换图解:

父进程创建子进程,然后子进程进行程序替换图解:

替换前:

如上,父进程创建子进程,然后子进程的代码和数据继承父进程的代码和数据的,然后即将发生替换的程序加载到内存中,页表中子进程的物理内存映射变大或变小为新进程的大小,
替换后:

替换后会发生写时拷贝,不仅仅是数据,代码也会,
当子进程需要执行不同的代码时,操作系统会将父进程的代码和数据拷贝一份,然后将新的程序加载到内存中,重新建立子进程的页表,并更新子进程页表中的映射关系。这一过程确保了父子进程的代码分离,使得它们互不干扰,写时拷贝技术保证了父子进程在没有对代码和数据进行修改时共享相同的物理内存,一旦发生写操作,就会为子进程分配新的物理空间,并拷贝数据,从而实现进程间的独立性,因此,当子进程进行程序替换时,父进程不受影响,因为替换过程中发生的写时拷贝确保了子进程的独立性

接下来理解两个问题

进程程序替换时,有没有创建新的进程?

当进程程序替换后,子进程的PCB,进程地址空间和页表都没有变,只是物理内存的数据和代码发生写时拷贝,但是这个子进程的pid并没有改变,也就是说,程序替换不创建新进程,只是进行进程的代码和数据的切换,

CPU是如何获取程序的入口地址的?

首先,在Linux中形成的可执行程序并不是杂乱无章的,是有格式的,Linux中这个格式成为ELF,这个可执行程序的最开始有可执行程序的表头,这个表里面有可执行程序的入口地址,我们之前了解到程序加载是惰性加载的,在程序加载到内存中可以先不把它的代码和数据加载到内存中,但一定要把表头加载到内存中,

在这个表里面有可执行程序的入口地址,这样CPU就能够从表中读取到程序的入口地址了

三、exec家族:

子进程替换父进程是用exec系列的函数来进行程序替换

如上,虽然有7个但是只有execve是系统调用接口,其他的都是调用这个接口进行了一次封装,

1、execl:

理解:

参数1:新替换程序的路径,(./当前路径,或者绝对路径如/usr/bin/ls)
参数2:新替换程序的名称,如ls,自己写的程序名
参数3:新替换程序的选项,如-a,-l,但是最后一个要是NULL表示结束
。。。:这是表示可变参数列表,可以传递不一样的参数个数
返回值:替换失败返回-1,替换成功的话子进程后面程序就不执行了,所以返回值也就没意义了

例如我要把子进程替换为ls进程:

execl("/usr/bin/ls","ls","-a","-l",NULL);

在代码中的使用:

int main()
{pid_t id = fork();if(id < 0){printf("进程创建失败\n");exit(1);}else if(id == 0){//子进程printf("子进程替换进程前\n");int ret = execl("/usr/bin/ls","ls","-a","-l",NULL);if(ret == -1){printf("进程替换失败\n");}printf("子进程替换进程后\n");exit(1);}else{//父进程printf("父进程正常执行\n");pid_t ret = waitpid(id,NULL,0);if(ret == id){printf("等待成功\n");}}return 0;
}

如上为执行结果:

可以看到execl之后的代码没有被执行,因为这些代码是属于原来子进程的代码,在execl之后这些代码就被替换了,原本的代码也就肯定不会执行

为什么,父进程能够等待得到已经被替换的进程呢?
这是因为虽然进程被替换了,但是并没有创建新的进程,替换后这个进程依然是父进程的子进程,pid也没有变,那么就可以正常等待

2、execlp:

理解:


参数1:这个和execl不同的是这个就只需要传执行的文件名就行了,路径会自动在环境变量中找
参数2:新替换程序的名称,如ls,自己写的程序名
参数3:新替换程序的选项,如-a,-l,但是最后一个要是NULL表示结束
。。。:这是表示可变参数列表,可以传递不一样的参数个数
返回值:替换失败返回-1,替换成功的话子进程后面程序就不执行了,所以返回值也就没意义了

这个就可以看做execl的升级版,也就是不需要手动传路径,会自动在环境变量中找

例如我要把子进程替换为ls进程:

execlp("ls","ls","-a","-l",NULL);

注意:
这虽然有两个ls,但是含义是不同的第一个参数是要执行程序的名字,第二个参数是可变参数列表

在代码中的使用:

int main()
{pid_t id = fork();if(id < 0){printf("进程创建失败\n");exit(1);}else if(id == 0){//子进程printf("子进程替换进程前\n");int ret = execlp("ls","ls","-a","-l",NULL);if(ret == -1){printf("进程替换失败\n");}printf("子进程替换进程后\n");exit(1);}else{//父进程printf("父进程正常执行\n");pid_t ret = waitpid(id,NULL,0);if(ret == id){printf("等待成功\n");}}return 0;
}

执行结果和execl是一样的

3、execv:

理解:

参数1:新替换程序的路径,(./当前路径,或者绝对路径如/usr/bin/ls)
参数2:这个是传一个 指针数组,里面成员就是类似于execl后面的参数

例图:(差不多就是下面这个意思)

int main()
{pid_t id = fork();if(id < 0){printf("进程创建失败\n");exit(1);}else if(id == 0){//子进程printf("子进程替换进程前\n");char* const myargv[] = { "ls" , "-a" , "-l" , NULL };int ret = execv("/usr/bin/ls",myargv);if(ret == -1){printf("进程替换失败\n");}printf("子进程替换进程后\n");exit(1);}else{//父进程printf("父进程正常执行\n");pid_t ret = waitpid(id,NULL,0);if(ret == id){printf("等待成功\n");}}return 0;
}

执行结果和execl是一样的

4、execvp:

char* const myargv[] = { "/usr/bin/ls" , "-a" , "-l" , NULL };int ret = execv("/usr/bin/ls",myargv);

这个和execl升级成execlp是一样的,就只是从自己在第一个参数中给路径变为只需传执行的文件名就行了,路径会自动在环境变量中找

5、execle和execve

理解:

参数1,参数2和返回值是一样的,就是多了一个环境参数,envp就是你自己设置的环境变量

putenv:

首先了解一下putenv函数:
这就是一个创建环境变量

putenv("环境变量=数值")

作用:在当前进程下创建一个环境变量并继承给子进程,并不会影响父进程

exec系列带e的函数中,就可以传环境变量:

int main()
{putenv("MYENV=6666666");pid_t id = fork();if(id < 0){printf("进程创建失败\n");exit(1);}else if(id == 0){//子进程printf("子进程替换进程前\n");execlp("./other","other",NULL);		printf("子进程替换进程后\n");exit(1);}else{printf("父进程正常执行\n");pid_t ret = waitpid(id,NULL,0);if(ret == id){printf("等待成功\n");}}return 0;
}

上面是bash的环境变量,下面是上述程序的运行结果,所以可以通过putenv来增加环境变量

也可以使用自己的环境变量,这个时候就需要使用execle或者execve了:

int main()
{pid_t id = fork();if(id < 0){printf("进程创建失败\n");exit(1);}else if(id == 0){//子进程printf("子进程替换进程前\n");char* const myenv[] = {"MYENV1=123","MYENV2=456","MYENV3=789",NULL};char* const myargv[] = {"other","-a","-b",NULL};execve("./other",myargv,myenv);		printf("子进程替换进程后\n");exit(1);}else{//父进程printf("父进程正常执行\n");pid_t ret = waitpid(id,NULL,0);if(ret == id){printf("等待成功\n");}}return 0;
}

如上,其中自己所写的other进程就是打印命令行参数和环境变量

int main(int argc,char* argv[],char* env[])
{cout<<"命令行参数"<<endl;for(int i = 0;argv[i];i++){cout<<i<<":"<<argv[i]<<endl;}cout<<"环境变量表"<<endl;for(int i = 0;env[i];i++){cout<<i<<":"<<env[i]<<endl;}return 0;
}

这样,在调用之后就可以打印出自己所传的命令行参数,和自己建立的环境变量表

想要理解好带e的函数,就需要先理解好exec在bash中的作用:

首先,在bash中,所有进程都是bash的子进程,那么这些子进程的命令行参数是从哪儿来的呢?就是通过exec系列的函数进行传参的,把第二个参数的选项作为命令行参数传给第一个参数指向的可执行性程序,所以在Linux中,当进程启动的时候就是父进程创建一个子进程,然后这个子进程的数据和代码替换为所执行的命令,exec系列的函数就是起到了类似于加载的作用

exec也可以加载脚本

比如下面写一个Python的脚本语言,

接着在子进程中调用脚本语言:

这样就能够运行脚本语言

所以,尽管Python和cpp是两种语言,但是竟然可以进行跨语言调用,这是为什么呢?

其实所有语言运行起来都是进程,只要是进程就可以被调用,所以,只要这个语言运行起来变成进程,那么就可以使用exec系列函数进行调用!!!

相关文章:

【Linux】进程控制-----进程替换

目录 一、为什么要进行进程替换&#xff1a; 二、进程替换的原理&#xff1a; 三、exec家族&#xff1a; 1、execl&#xff1a; 2、execlp&#xff1a; 3、execv&#xff1a; 4、execvp&#xff1a; 5、execle和execve ​编辑 putenv&#xff1a; 一、为什么要进行进程…...

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本。 原因是&#xff1a;当前操作系统版本为Windows Server 2016 Standard版本&#xff0c;其自带的Microsoft .NET Framework 版本为4.6太低&#xff0c;不满足要求。 根据报错的提示&#xff0c;点击链接…...

使用ECharts创建带百分比标注的环形图

在数据可视化领域&#xff0c;环形图是一种非常有效的图表类型&#xff0c;它能够清晰地展示各部分与整体的关系。今天&#xff0c;我们将通过ECharts来创建一个带百分比标注的环形图&#xff0c;并详细解释如何实现这一效果。 1. 数据准备 首先&#xff0c;我们定义了一些基础…...

学习threejs,设置envMap环境贴图创建反光效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.CubeTextureLoader 立…...

go语言里的mkdir mkdirall有什么区别?

在Go语言中&#xff0c;os.Mkdir 和 os.MkdirAll 都是用来创建目录的函数&#xff0c;但它们之间存在一些关键的区别。 ### os.Mkdir - **功能**&#xff1a;os.Mkdir 用于创建一个单一的目录。如果该目录已经存在&#xff0c;则会返回一个错误。 - **参数**&#xff1a; - na…...

使用Python OpenCV实现图像形状检测

目录 一、环境准备 二、读取和预处理图像 读取图像 灰度化 滤波去噪 三、边缘检测 四、查找轮廓 五、绘制轮廓 六、形状分类 七、显示结果 八、完整代码示例 九、总结 图像形状检测是计算机视觉领域中的一项关键技术,广泛应用于工业自动化、机器人视觉、医学图像处…...

继上一篇,设置弹框次数以及自适应图片弹框,部分机型(vivo)老手机不显示的问题

上一篇写的本来测试好多型号都无事, 今天下午公司的战斗机vivo横空冒出… 晕 弹框直接显示都出不来了,现在还有用这种老的机型的,但是没办法咯~ 前端遇到这种兼容性的问题就要勇于解决 主要解决了这几点: // 添加图片加载事件 <imgv-if"imageUrl":src"image…...

基于RISC-V 的代理内核实验(使用ub虚拟机安装基本环境)

1.安装支撑软件 第一步&#xff0c;安装依赖库 RISC-V交叉编译器的执行仍然需要一些本地支撑软件包&#xff0c;可使用以下命令安装&#xff1a; $ sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bis…...

【MMKV】HarmonyOS中的优秀轻量化存储方式

MMKV 引言 在移动应用开发的世界里&#xff0c;数据存储和管理是至关重要的一环。随着技术的不断进步&#xff0c;开发者们对于高性能、轻量级、易用的数据存储解决方案的需求日益增长。MMKV&#xff08;Memory Mapped Key-Value&#xff09;正是这样一个开源的高性能key-val…...

docker安装hadoop环境

一、使用docker搭建基础镜像 1、拉取centos系统镜像 # 我这里使用centos7为例子 docker pull centos:7 2、创建一个dockerfiler文件&#xff0c;用来构建自定义一个有ssh功能的centos镜像 # 基础镜像 FROM centos:7 # 作者 #MAINTAINER hadoop ADD Centos-7.repo /etc/yum.re…...

开源多媒体处理工具ffmpeg是什么?如何安装?使用ffmpeg将M3U8格式转换为MP4

目录 一、FFmpeg是什么二、安装FFmpeg&#xff08;windows&#xff09;三、将M3U8格式转换为MP4格式 一、FFmpeg是什么 FFmpeg是一款非常强大的开源多媒体处理工具&#xff0c;它几乎可以处理所有类型的视频、音频、字幕以及相关的元数据。 FFmpeg的主要用途包括但不限于&…...

算法刷题Day5: BM52 数组中只出现一次的两个数字

描述&#xff1a; 一个整型数组里除了两个数字只出现一次&#xff0c;其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 要求&#xff1a;空间复杂度 O(1)&#xff0c;时间复杂度O(n)。 题目传送门 is here 思路&#xff1a; 方法一&#xff1a;最简单的思路就…...

55 基于单片机的方波频率可调

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 采用STC89C52单片机最小系统&#xff0c;设计DAC0832、放大器、与示波器显示方波&#xff0c;四位数码管显示频率&#xff0c;两个按键可调。 二、硬件资源 基于KEIL5编写C代码&#xff0c;PROT…...

23.useUnload

在 Web 应用开发中,处理页面卸载(unload)事件是一个重要但常常被忽视的方面。无论是提醒用户保存未保存的更改,还是执行一些清理操作,都需要在用户即将离开页面时进行处理。useUnload 钩子提供了一种简洁的方式来在 React 组件中处理 beforeunload 事件,使得在用户试图关…...

linux环境搭建

1、**连接外网** ssh在192.168.4.x上运行sudo ip link set ens160 down ssh切换到192.168.3.x(外网ip)&#xff0c;运行sudo ip route add default via 192.168.2.1 dev ens192 onlink //连接外网 使用完外网后 ssh在192.168.3.x上运行sudo ip link set ens160 up ssh在1…...

《C++与生物医学的智能融合:医疗变革新引擎》

在当今科技飞速发展的时代&#xff0c;人工智能正以前所未有的深度和广度渗透到各个领域&#xff0c;为传统行业带来革新与突破。其中&#xff0c;将 C与生物学、医学等领域知识相结合&#xff0c;开发用于处理生物医学数据、辅助疾病诊断和治疗的人工智能应用&#xff0c;成为…...

Matlab 绘制雷达图像完全案例和官方教程(亲测)

首先上官方教程链接 polarplothttps://ww2.mathworks.cn/help/matlab/ref/polarplot.html 上实例 % 定义角度向量和径向向量 theta linspace(0, 2*pi, 5); r1 [1, 2, 1.5, 2.5, 1]; r2 [2, 1, 2.5, 1.5, 2];% 绘制两个雷达图 polarplot(theta, r1, r-, LineWidth, 2); hold …...

Lua的环境与热更

一、global_State,lua_State与G表 Lua支持多线程环境&#xff0c;使用 lua_State 结构来表示一个独立的 Lua 线程&#xff08;或协程&#xff09;。每个线程都需要一个独立的全局环境。而lua_State 中的l_G指针&#xff0c;指向一个global_State结构&#xff0c;这个就是我们常…...

HTML CSS JS基础考试题与答案

一、选择题&#xff08;2分/题&#xff09; 1&#xff0e;下面标签中&#xff0c;用来显示段落的标签是&#xff08; d &#xff09;。 A、<h1> B、<br /> C、<img /> D、<p> 2. 网页中的图片文件位于html文件的下一级文件夹img中&#xff0c;…...

若依解析(一)登录认证流程

JWTSpringSecurity 6.X 实现登录 JWT token只包含uuid ,token 解析uuid&#xff0c;然后某个常量加UUID 从Redis缓存查询用户信息 流程图如下 感谢若依&#xff0c;感谢开源&#xff0c;能有这么好系统供我学习。 设计数据库&#xff0c;部门表&#xff0c;用户表&#xff0c…...

Redis设计与实现第17章 -- 集群 总结1(节点 槽指派)

集群通过分片sharding来进行数据共享&#xff0c;并提供复制和故障转移功能。 17.1 节点 一个Redis集群通常由多个节点node组成&#xff0c;刚开始每个节点都是相互独立的&#xff0c;必须将各个独立的节点连接起来&#xff0c;才能构成一个包含多个节点的集群。通过CLUSTER …...

汽车控制软件下载移动管家手机控车一键启动app

移动管家手机控制汽车系统是一款实现车辆远程智能控制的应用程序‌。通过下载并安装特定的APP&#xff0c;用户可以轻松实现以下功能&#xff1a;‌远程启动与熄火‌&#xff1a;无论身处何地&#xff0c;只要有网络&#xff0c;即可远程启动或熄火车辆&#xff0c;提前预冷或预…...

推荐几个可以免费下载网站模板的资源站

推荐几个可以免费下载网站模板的资源站&#xff0c;上面有免费的wordpress模板和帝国CMS模板可以下载。 模板帝 Mobandi.com 模板帝是一个提供丰富网站模板资源的平台&#xff0c;旨在帮助用户快速构建和美化自己的网站。无论是个人博客、企业官网还是电子商务平台&#xff…...

H3C OSPF实验

实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF &#xff0c;实现全网互通为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 实验解法 一、配置IP地址 [R1]int l0 [R1-LoopBack0]ip add 1.1.1.1 32 […...

Vue框架开发一个简单的购物车(Vue.js)

让我们利用所学知识来开发一个简单的购物车 &#xff08;记得暴露属性和方法&#xff01;&#xff01;&#xff01;&#xff09; 首先来看一下最基本的一个html框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…...

Windows Terminal Solarized Dark 配色方案调整

起因 Widnows 10/11 下面自带的 Terminal 还是比较方便的&#xff0c;因为不需要安装额外的 Terminal 软件。 我喜欢 Solarized Dark 配色方案&#xff0c;虽然有人批评这个配色方案比较老&#xff0c;但我觉得它比较优雅&#xff0c;尤其对外这种眼神比较差的人&#xff0c;比…...

PyTorch张量运算与自动微分

PyTorch张量运算与自动微分 PyTorch由Facebook人工智能研究院于2017年推出&#xff0c;具有强大的GPU加速张量计算功能&#xff0c;并且能够自动进行微分计算&#xff0c;从而可以使用基于梯度的方法对模型参数进行优化&#xff0c;大部分研究人员、公司机构、数据比赛都使用P…...

【从零开始的LeetCode-算法】3264. K 次乘运算后的最终数组 I

给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a; 找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…...

【Linux】gdb / cgdb 调试 + 进度条

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、Linux调试器-gdb &#x1f31f;开始使用 &#x1f320;小贴士&#xff1a; &#x1f31f;gdb指令 &#x1f320;小贴士&#xff1a; ✨watch 监视 ✨打条件断点 二、小程序----进…...

Jenkins Nginx Vue项目自动化部署

目录 一、环境准备 1.1 Jenkins搭建 1.2 NVM和Nodejs安装 1.3 Nginx安装 二、Jenkins配置 2.1 相关插件安装 2.2 全局工具安装 2.3 环境变量配置 2.4 邮箱配置&#xff08;构建后发送邮件&#xff09; 2.5 任务配置 三、Nginx配置 3.1 配置路由转发 四、部署项目 …...

网站换了域名做跳转/品牌营销策划方案

自动化测试思路 一、首先明确为什么要设计项目自动化测试框架&#xff1f; 可以进行分类有序的来管理项目自动化的代码和文档等希望可以做到一旦自动化测试代码写完调试通之后&#xff0c;就不要再修改代码了。 因为一旦修改&#xff0c;就得担心代码出问题&#xff0c;又得重…...

山西高端网站建设/网络服务器是指什么

现在市面上厂家宣传制氧机的噪音普遍为45-48分贝&#xff0c;但每个厂家宣传的都是实验室检测的噪音值&#xff0c;且检测的机器&#xff0c;可能针对性的制造。也经常有网友反馈&#xff0c;商家宣传的噪音和实际买到机器的噪音值&#xff0c;差别很大。所以夜猫购买噪音测试仪…...

外贸批发网站/优化落实疫情防控

在2017年Zen架构处理器问世之前&#xff0c;AMD的产品路线图也经历过很多折腾&#xff0c;延期也是常态&#xff0c;不过从锐龙Ryzen、EPYC霄龙上市开始&#xff0c;现在的Zen架构产品线路线图稳定多了&#xff0c;今年7nm Zen 2架构的锐龙3000、EPYC罗马处理器都会如期上市。7…...

做网上商城网站哪家好/网站搭建需要什么

Java四种引用类型 1.引用的基本概念 强引用&#xff1a;当我们使用new创建对象时&#xff0c;被创建的对象就是强引用&#xff0c;如Object object new Object()&#xff0c;其中的object就是一个强引用了。如果一个对象具有强引用&#xff0c;JVM就不会去GC它&#xff0c;JVM…...

深圳网站论坛建设/网络营销方案的制定

今日&#xff0c;有员工反映使用的Foxmail6.5客户端中的联系人又丢失的情况&#xff0c;使用SMS远程查看后发现&#xff0c;此员工使用两个邮件账号&#xff0c;其中邮件1中的地址薄的个人文件夹中存储了多个邮件地址&#xff0c;而邮件2中的个人地址薄中则无邮件地址。发生此问…...

公司网站域名com好还是cn好/app拉新推广平台代理

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;###Android面试之Handler相关学习1.Android消息机制之Looper.java源代码学习1). 准备阶段,在子线程中调用Looper.prepare()方法或者在主线程调用Looper.prepareMai…...