进程控制3——进程程序替换

进程的创建有fork,进程的退出有main函数的return,exit,_exit函数
而进程的退出中,一个进程的退出只能有三种情况,退出成功结果对/不对,或者是运行异常收到信号终止
但是我们发现我们用代码创建的子进程它是与父进程共同执行一套代码,在不发生写时拷贝的情况下还会使用同一套数据
那有没有可能让父子进程执行不同的代码,拥有不同的数据呢?
答案是可以的!这就是我将要介绍的——进程程序替换

文章目录

  • 1.初步认识程序替换函数
  • 2.多进程下的程序替换
  • 3.从系统层面理解程序替换
  • 4.程序替换的使用
    • 延伸
  • 5.程序替换函数
    • a. 程序替换与环境变量
    • b. 程序替换函数与环境变量
    • c. 库函数与系统调用

1.初步认识程序替换函数

我们直接上代码展示程序替换需要用到的一个函数execl:
在这里插入图片描述
我们直接使用它:
在这里插入图片描述
代码运行结果:
在这里插入图片描述
我们能发现到两个现象,这个代码帮我们运行了一条指令:ls -l -a,并且在上面程序中,并没有执行return的上一句代码。
可见execl确实能够帮我们执行其他程序。我来介绍一下函数的参数:

path:很明显是一个路径,这个路径是我们想要执行程序的路径 + 可执行程序文件名
arg:我们可以看到它后面有三个点,这三个点代表的意思是可变参数列表,
	而包括arg这个参树,我们在命令行怎么用这个程序,我们就用字符串怎么包含命令行中空格分隔的每段字符
	函数的结尾必须以NULL结尾

2.多进程下的程序替换

接下来我们就用代码来展示多进程下的程序替换:
在这里插入图片描述
在这里插入图片描述
可以看到,使用起来跟单进程没有什么大的区别,并且也没有打印hello world。

3.从系统层面理解程序替换

下面我就用ls命令的文件来代替替换的程序
首先我们要了解的第一个是使用exel进程程序替换后,是否又创建进程了呢?有的话它应该会有pcb和自己的地址空间、页表,没有的话那又是如何实现的呢?这里先说一下单进程程序替换的原理:
我们知道一个程序跑起来之后会形成一个进程,创建自己的的pcb、进程地址空间、页表等。
在这里插入图片描述

当我们在执行自己的可执行程序的之后,先将可执行程序加载到内存中,然后操作系统使用相关的数据结构体来将它管理起来,当执行到execl函数的时候,操作系统会根据execl中提供的路径将ls的可执行文件加载到内存中,覆盖我们可执行的代码段和代码数据的区域,然后开始执行ls中的代码:

在这里插入图片描述
有人可能就会说了,重新覆盖之后操作系统哪知道它该从哪里开始执行呢?其实这里就有两个小知识点:
在Linux中可执行程序文件中不只有代码段和代码数据还有开头会存储一个地址这个地址记录了程序从哪里开始执行(可执行文件的内部布局遵循ELF的规则),而cpu中又有一个寄存器eip,他会记录下一条将要执行代码的地址。所以才能够如此丝滑的进行程序切换。而这也解决了我们的疑问:
首先,程序替换并不会产生新的进程,其次为什么上面不会执行execl后的代码,原代码和代码数据被覆盖,那么自然只会执行覆盖后的代码了
那么多进程下的程序替换又是怎么样的呢?
在这里插入图片描述
当执行到execl之后,ls文件要覆盖物理内存中的原有数据,但是内存中的数据不知一个进程有,所以会触发写时拷贝机制,然后子进程映射到新的物理内存:

在这里插入图片描述

4.程序替换的使用

我们上面说了程序替换能够使用命令ls,那能不能用我们自己的程序呢?
调用c++程序
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
调用python脚本:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ls命令是用C语言写的,我们能切换,我们也能切换c++程序,我们还能调用python脚本,当然其它比如shell脚本、Java脚本也能切换。我们现在就明白为什么在一个工程中会出现多种语言的协同开发了。那由此就产生一个问题,为什么能够切换呢?一个是C语言一个是python脚本完全不搭边啊。
那我们就需要更为底层的理解这个现象了,不论是c++形成的可执行程序被执行还是python脚本被解释器解释执行,本质都是启动了一个进程,那都是进程了,还分什么c++,python吗?那肯定是不分了,不都是内核数据结构 + 代码 + 代码数据吗?那我用C语言这个进程切换执行本应该是另一个进程执行的的东西肯定是可以的了。所以就有系统高于一切的说法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里也说明了程序替换的时候没有产生新进程。

延伸

现在我们再理解一下运行一个程序。
我们说运行一个程序首先就是把它加载到内存中。
那为什么要加载到内存中呢?
这是由于计算机的体系结构决定的,cpu不跟外设直接交互。
如何加载?
我们发现execl函数切换了代码段和代码数据,这不就是把ls可执行程序文件加载到了内存中吗?也说明execl也充当着将文件加载到内存中的加载器的功能。
那在程序加载到内存中的时候也会生成pcb、虚拟地址空间、页表等等内核数据结构,那创建内核数据结构和加载可执行到内存那个先执行呢?
我们在创建进程的时候有没有可能不调度这个进程,因为操作系统太“忙”了,没有多余的内存了,而又从上面的情况来说,我们创建好一个子进程后执行一条代码后,切换程序,它的pid没有改变,这可不可以说明在切换程序(新的程序加载到内存时)就已经有内核数据结构了(因为有进程pid)。所以创建内核数据结构,和加载可执行文件到内存,一定是先创建好内核数据结构。

5.程序替换函数

关于程序替换相关的函数不止上面的一个execl还有很多:
在这里插入图片描述
在这里简单介绍一下exec*系列的函数

带l的意思是传的参数是可变参数列表的形式传
带p的意思是,第一个参数不用写绝对路径 + 文件名,只要文件名就可以
带v的意思是vector,数组的意思,就是以数组的形式传
带e的意思是,传的参数的第三个参数是环境变量数组

a. 程序替换与环境变量

我们在这里要着重说一下参数中有环境变量的函数。
我们知道子进程会继承父进程中的环境变量,这一点的验证很简单,并且方法多种,我们只用其中一种:
在这里插入图片描述
这样可以查看该进程中的所有环境变量:
在这里插入图片描述
我们知道在命令行中启动的进程都是shell的子进程,那么我们在shell中添加一个环境变量我们再来看该程序中的环境变量:
在这里插入图片描述
我们看到是这样的结果,那我们在我们自己的进程中添加的子进程中的环境变量是什么情况呢?
在这里插入图片描述

在这里插入图片描述
在这里我们介绍一个函数putenv:
在这里插入图片描述
很明显它可以为在代码中该进程添加 一个环境变量:
在这里插入图片描述
在这里插入图片描述
我们可以看到,父进程确实会将环境变量传递给子进程。那么我们知道当使用程序替换函数的时候,物理内存中的代码数据将会被覆盖重写,页表也重新映射,那子进程中的环境变量也肯定在内存中,那当子进程程序替换后环境变量还在不在呢?
在这里插入图片描述

在这里插入图片描述

我们发现它也是在的,这是为什么呢?我们需要从底层来认识:
在这里插入图片描述
环境变量在栈区之上通过地址空间可以让子进程继承父进程的环境变量,所以我们可以得出程序替换只会替换新程序的代码和数据,环境变量并不会被替换

b. 程序替换函数与环境变量

我们现在来用一下这个带有环境变量参数的函数:
test.c:
在这里插入图片描述
mytest.cc:
在这里插入图片描述

在这里插入图片描述
假如我们变化函数的参数,传的是我们自己的数组呢?
在这里插入图片描述
在这里插入图片描述
我们看到它会发生覆盖!所以程序替换函数中的环境变量传参是覆盖式传递。那我们想要用父进程给子进程添加环境变量呢?也很简单,在父进程中用putenv就可以了。

至此我们就可以知道程序替换函数可以将命令行参数与环境变量传递给被替换换的程序中

c. 库函数与系统调用

在这里插入图片描述
由上图就可以知道,库函数中这么多的程序替换函数必然是封装了右边的系统调用,那为什么一个函数要被封装成这么多的接口呢?那自然也是为了在实际使用中能够更加的灵活。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面试鸭 - 专注于面试刷题的网站

网上面试题有很多,但此套面试题真实、原创、高频,全网最强。 题目涵盖大中小公司,真实靠谱,有频率和难度的标记,助你成为Offer收割机。 面试鸭地址:https://mianshiya.skyofit.com/ 本套题是我原创&…

【Mysql】学习笔记

目录 基本操作登录指令:启动、关闭、重启mysql指令(适用于centos7):查看mysql运行状态:删除和创建表 修改密码(ubuntu18.04可行,其余版本行不行不知道)3 使用MYSQL了解数据库和表 4 …

java基础--JVM的学习1--jvm基础和class文件的组成

文章目录 JVM概念JVM功能 JVM组成class文件一般信息 常量池字段方法 反编译 使用到了idea的jclasslib插件 JVM概念 全称Java Virtual Machine,java虚拟机。 将java字节码文件正确的加载和允许。 JVM功能 解释运行 对字节码指令实时的解释成机器码,让计…

【数字人】7、GeneFace++ | 使用声音和面部运动系数的关系作为 condition 来指导 NeRF 重建说话头

文章目录 一、背景二、相关工作2.1 唇形同步的 audio-to-motion2.2 真实人像渲染 三、方法3.1 对 GeneFace 的继承3.2 GeneFace 的结构3.2.1 Pitch-Aware Audio-to-Motion Transform3.2.2 Landmark Locally Linear Embedding3.2.3 Instant Motion-to-Video Rendering 四、效果 …

学人工智能等于失业?

随着科技的快速发展,人工智能已经渗透到我们生活的方方面面,从手机、智能家居到自动驾驶汽车,都离不开人工智能技术的支持。 因此,学习人工智能已经成为越来越多人追求高薪职业的选择。在这篇文章中,我们将探讨学习人…

Linux基本指令及周边(第一弹)

文章目录 前言mkdir指令(重要):tree指令rmdir指令 && rm 指令(重要):touch指令ls指令pwd指令cd 指令用户家目录man指令(重要):mv指令(重要)cat指令绝…

Linux 系统误将 chmod 权限改成 了 000,如何恢复?

Linux 系统误将 chmod 权限改成 了 000,如何恢复? busybox 是 Linux 标配,含有大多数主流 Linux 命令,你可以把它的存在当作救急备份。简单功能都可以调用 busybox 完成。这也就意味着很多原始命令出故障的情况下都可以用 busybox 暂时替代。…

调用本地大模型实现聊天机器人ChatBot

AWS Instance本地部署大模型 AWS上申请带GPU的instance,例如g4dn系列,申请instance后安装CUDA的driver,driver安装完成后,就可以在带gpu的instance上部署开源的大模型了。如果想了解在aws上部署本地模型细节,可以阅读…

upload-labs关卡11(双写后缀名绕过)通关思路

文章目录 前言一、回顾前几关知识点二、靶场第十一关通关思路1、看源代码2、bp抓包双写后缀名绕过3、检查文件是否成功上传 总结 前言 此文章只用于学习和反思巩固文件上传漏洞知识,禁止用于做非法攻击。注意靶场是可以练习的平台,不能随意去尚未授权的…

主键问题以及分布式 id

分布式 id 需要处理的问题主要是同一时间在多台机器中保证生成的 id 唯一,为了这么做我们可以这么做: 分布式 id 生成策略 先说几个已经被淘汰的策略引出分布式 id 的问题 1,UUID:UUID 随机并且唯一,在单一的数据库…

JS进阶——构造函数数据常用函数

1、深入对象 1.1 创建对象三种方式 1.1.1 利用对象字面量创建对象 1.1.2 利用new Object创建对象 1.1.3 利用构造函数创建对象 1.2 构造函数 构造函数:是一种特殊的函数,主要用来初始化对象 使用场景:常规的{...}语法允许创建一个对象。…

【数据结构】手撕双向链表

目录 前言 1. 双向链表 带头双向循环链表的结构 2. 链表的实现 2.1 初始化 2.2 尾插 2.3 尾删 2.4 头插 2.5 头删 2.6 在pos位置之前插入 2.7 删除pos位置 3.双向链表完整源码 List.h List.c 前言 在上一期中我们介绍了单链表,也做了一些练习题&…

IC设计企业,如何安全、可控、高效的传输设计文档和研发数据?

近年来,半导体的应用领域不断拓展,在全球经济和社会发展中的重要性与日俱增,半导体芯片是数字经济的核心,承载着现代产业发展,具有举足轻重的价值。从半导体行业的角度,IC设计是关键的一环,我国…

中科创达:坚定看好未来十五年的大模型机遇

中科创达是一家成立于2008年的智能操作系统产品和技术提供商,15年前公司成立的时候正赶上了安卓操作系统将功能手机推向了智能手机,截至目前,已赋能超过近9亿台手机走向市场。2014年中科创达开始拓展智能汽车方向,2015年拓展物联网…

CSGO的那些事儿:CS2这么差,为什么不改回CS1?

揭秘csgo饰品涨价背后的残酷真相 1、V社现在更新内容集中在游戏性的修复方面。 所以原来期望的新地图新大行动等,要等到游戏本体趋于稳定后才更新。但是,因为距离下一个大型活动,也就是丹麦major还有5个月时间,那这之间必然要有一…

kubernetes 高可用集群

目录 一、haproxy负载均衡 二、pacemaker高可用 三、部署control-plane 四、部署worker node 实验环境 主机名 IP 角色 docker 192.168.67.10 harbor k8s1 192.168.67.11 control-plane k8s2 192.168.67.12 control-plane k8s3 192.168.67.13 control-plane k8s…

opencv(5): 滤波器

滤波的作用:一幅图像通过滤波器得到另一幅图像;其中滤波器又称为卷积核,滤波的过程称为卷积。 锐化:边缘变清晰 低通滤波(Low-pass Filtering): 目标:去除图像中的高频成分&#…

【打卡】牛客网:BM55 没有重复项数字的全排列

自己写的&#xff1a; 虽然题目要求了排序&#xff0c;但是我没排序也可以通过。 class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param num int整型vector * return int整型vector<vec…

23届计科,想找Java开发之类,真的是很难吗?

23届计科&#xff0c;想找Java开发之类&#xff0c;真的是很难吗&#xff1f; 你的投递信息(投递多少家&#xff0c;如何跟hr打招呼&#xff0c;已读不回如何应对等)都亮- -下才能知道问题出在 哪。最近很多小伙伴找我&#xff0c;说想要一些Java的资料&#xff0c;然后我根据…

Ubuntu 下C++数字雨

以前写过一个Window下的数字雨&#xff0c;像黑客帝国里那样的01数字&#xff0c;现在补充一版Linux下的。使用了curses库&#xff0c;安装方法与使用方法参照 Linux下curses函数库的详细介绍_libcurses库-CSDN博客 5-linux学习笔记之-----curses-CSDN博客 效果如下&#xf…