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

linux进程控制——进程替换——exec函数接口

        前言: 本节内容进入linux进程控制板块的最后一个知识点——进程替换。 通过本板块的学习, 我们了解了进程的基本控制方法——进程创建, 进程退出, 进程终止, 进程替换。

        进程控制章节和上一节进程概念板块都是在谈进程, 也就是说, 进程的相关内容博主整整通过两个大章, 一共12篇文章进行讲解, 并且几乎每一篇的字数都达到了纯论述五千字左右, 少的也有3500字以上, 多的甚至将近破7000。由此可以看到进程非常重要以及学习难度大。 其中进程概念是一个大难点, 里面知识点多, 晦涩难懂, 博主足足讲解了9篇,并且文章很长。 而进程控制有了前面进程概念的基础, 在理解起来就相对轻松一些, 并且内容较少, 论述性文字可能少一些, 博主通过包括本篇在内的3篇文章就可以完成讲解。 总之, 进程很重要, 希望友友们耐心学习。下面, 进入本节的学习吧。

        ps:本节适合了解进程概念, 以及进程的创建, 退出, 终止和等待的友友们进行观看。

目录

 什么是进程替换

单进程的进程替换

进程替换的原理

​编辑多进程的程序替换

 程序替换有没有创建新的进程

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

详解exec接口

execl

execlp

execv

exec加载器

exec执行用户写的程序——含execle讲解

putenv

execle


 什么是进程替换

linux下有一种接口可以进行进程替换工作——exec

使用man手册, 然后就可以观察到详细内容:

上面的这些接口, 他们的工作都是一样的——把一个文件(可执行程序)替换程当前进程。 

单进程的进程替换

我们先以单进程, 也就是没有创建子进程为例, 来使用一下, 试验一下进程替换函数——exec, 我们这里使用的是execl函数, 因为它是最简单的一个进程替换函数。 

execl的参数是可变参数, 最后一个参数一定是NULL。如下图:

运行结果如下:

运行后我们就发现我们自己写的程序竟然能够将系统命令封装起来进行执行——这个过程, 就叫做程序替换。 而程序替换的现象就是把别人的程序替换一下, 在执行替换函数的之前逻辑的代码会跑,但是之后逻辑的代码就不会跑了。

进程替换的原理

        程序替换我们从上面的实验就能看到, 其实就是调用一下系统里面的其他程序, 生成一个新的进程。这个新的进程会生成一个PCB。

        首先, 会生成如下图:

        然后调用ls, 那么就会又将ls的代码数据加载到物理内存, 拷贝一份PCB、虚拟地址空间和页表。 ——这是我们以前对于创建子进程的理解。 但是对于execl, execl执行的程序不会执行上面的操作。而是直接将execl里面的程序的代码替换给物理内存里面原本进程加载的位置。 ——这, 就是程序替换。 

多进程的程序替换

然后再看一下多进程的程序替换是什么样子的。 多进程的程序替换, 我们就是要创建一个子进程,然后再执行一次程序替换。 现在我们就来实验一下:

        首先, 创建一个父进程:

然后, 根据父进程, 创建, 拷贝出子进程。 

        然后程序替换子进程:

在没有运行程序前, 什么都不会打印。

开始运行程序后, 父子进程都会被打印。 

5秒后子进程被替换, 执行ls。 同时执行完毕被等待, 资源被回收, 我们就能看到只会打印父进程了!!

 程序替换有没有创建新的进程

        刚开始运行的时候, 父子进程的PID一直没有变。 我们知道, 创建新进程需要创建新的PCB和地址空间以及页表。 然后拷贝所有的数据, 当涉及物理内存的修改时发生写时拷贝。 而父子进程的PID没有变, 也就是说, 程序替换不创建新进程, 只进行进程的代码和数据的替换工作!!

        那么, 为什么execl之后的代码没有被执行呢? 因为对于execl之后的代码来说, 这些代码的本质上也是属于原本的进程的。 但是当这个execl被执行, 这个进程的代码和数据就被替换了。 原本的代码和数据当然就没有用了!!

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

        我们的CPU是如何获取程序的入口地址的呢? 这是因为, linux中形成的可执行程序, 是有格式的——ELF。 也就是可执行程序的表头, 这个表描述了可执行程序的段, 比如代码段, 数据段等等。 同时也有一个可执行程序的入口地址。 

详解exec接口

        现在重新看一下这些exec接口

execl

现在看博主写的这个程序:

        上面的程序调用了execl。 首先我们思考一下, 执行一个程序的第一件事是什么? 是不是要找到这个程序?所以, execl函数里面的第一个参数就是一个路径,是我们要执行的程序的绝对路径(相对路径也可, 但是执行命令的地方会被限制)。然后找到这个程序后, 我们是不是还要看看执行什么选项? 要以什么方式打开这个程序? 所以, 第二个参数以后的参数, 都是一些选项, 并且这些选项的最后一个必须是NULL, 就相当于一个链表。 链表里面存的是这些选项!!!为了区分表尾, 就必须把最后一个选项弄成NULL。

execlp

这个函数名比execl多了一个p, 这个p就叫做PATH路径。 代表execlp自己会在默认的PATH环境变量中查找。 ——也就是说, 我们传参时不需要传路径。 只需要传执行的文件名就行了!

就比如下图:

而之所以还要加上ls, 是因为PATH中只有路径, 没有文件名。

        PATH中的路劲, 加上ls文件名。 就能解决第一个——如何找到这个程序的问题。 

execv

        现在看一下execv, v就是数组, 第一个参数还是路径加文件名。 大师第二个参数是一个字符串指针数组。 

        这个数组就是将原本的ls -al变成ls, -a, -l。 这三个字符串分别作为字符串元素让这个指针数组指向他们。

下面是实验代码:

exec加载器

        那么, 现在问题来了。 请问ls是程序吗? 是程序, 那么是程序, ls就有main, 是不是也有命令行参数? 有了命令行参数, ls的命令行参数是从哪里来的呢? ——是从execv系统调用, 或者execl, execlp里面的参数里面获得的。 execl系列函数作为系统调用, 会把第二个参数的选项作为命令行参数传给第一个参数指向的可执行性程序。 

        在linux中, 所有进程都是别人的子进程, 在命令行当中, 所有的进程都是bash子进程。 所以, 所有进程在启动的时候, 都是使用exec系列函数启动执行的。 程序替换的本质就是将要替换的进程的数据和代码加载到内存当中。 所以, exec系列函数起到的就是加载器的效果。 

exec执行用户写的程序——含execle讲解

现在我们创建一个程序, 让我们原本的程序去调用这个程序:

ps:注意, 在c++当中的后缀可以是cpp, cxx, cc

利用makefile一次创建两个可执行程序,需要使用PHONY, 如下:

然后就会生成下面两个文件:

现在我们写一个程序调用otherExe.exe

运行后, 我们执行process-7-11.exe其实就是执行了otherExe.exe

 也可以调用脚本语言, 我们先创建一个shell脚本:

运行结果如下:

由上面两个例子我们就可以知道:语言和语言之间可以替换, 无论是我们的可执行程序, 还是脚本。 那么为什么能够跨语言调用呢?

其实所有语言运行起来, 本质上都是进程!!!

execl根本不是运行语言, 而是运行的进程, 只要是进程, 那么就可以被调用。 ——也就是说, 所有的语言, 只要最终可以变成进程, 那么最终都可以使用C/C++调用!!!

那么, 现在看一下命令行参数:我们将命令行参数传给myargv:

然后命令行参数就可以被打印出来:

我们也可以打印环境变量:

 

部分的打印结果如下:

         那么, 环境变量是什么时候给进程的呢? 环境变量也是数据, 当我们创建子进程的时候, 黄金变量就已经被子进程继承下去!!!

        所以, 我们即便没有传递命令行参数, 也是可以的!!!extern char** environ, 在进程定义的时候已经被父进程初始化了。 只要我们不写, 那么最终就是父进程的环境变量表!!!

        也就是说, 只要我们不写, 那么就是一张环境变量表。

        所以, 程序替换的时候, 环境变量的信息, 不会被替换。 所有如果我们相隔i紫禁城传递环境变量, 能怎么传递?

  • 第一种方式是新增环境变量——使用putenv在父进程中创建环境变量让子进程继承。
  • 第二种方式是彻底替换环境变量——使用execle替换

putenv

        我们先创建一个环境变量

        运行后, 我们的程序也有了这个环境变量:

        putenv的使用方法:putenv(“环境变量=数值") 在当前进程下创建一个环境变量并继承下去。

        在当前进程创建环境变量, 不会影响bash进程。

 

execle

传环境变量:带e的execl

 execle的参数如下:

 运行后就是下图: 可以看到运行结果里面也有MYNEWENV=666

 我们自定义这一张环境变量表

然后打印出来就是如下, 只会打印出我们自己定义的环境变量,  不会打印系统默认的环境变量。

自定义环境变量表, 采用的是覆盖, 而不是追加, 这就是彻底替换环境变量。

以上, 就是本届的全部内容, 下面是博主整理的本节的笔记:

相关文章:

linux进程控制——进程替换——exec函数接口

前言: 本节内容进入linux进程控制板块的最后一个知识点——进程替换。 通过本板块的学习, 我们了解了进程的基本控制方法——进程创建, 进程退出, 进程终止, 进程替换。 进程控制章节和上一节进程概念板块都是在谈进程…...

Apache解析漏洞~CVE-2017-15715漏洞分析

Apache解析漏洞 漏洞原理 # Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令。比如如下配置文件: AddType text/html .html AddLanguage zh-CN .cn# 其给 .html 后缀增加了 media-type ,值为 text/html ;给 …...

Xilinx管脚验证流程及常见问题

1 流程 1.1 新建I/O Planning Project I/O Planning Project中可以不需要RTL的top层.v代码,仅图形化界面即可配置管脚约束XDC文件的生成: Create I/O Ports: 导出XDC文件和自动生成的top_interface.v文件: 1.2 新建test Project …...

格雷厄姆的《聪明的投资者》被誉为“投资圣经”

本杰明格雷厄姆的《聪明的投资者》(The Intelligent Investor: A Book of Practical Counsel)是投资领域的一部经典之作,被誉为“投资圣经”。以下是对该书的详细解析: 一、书籍基本信息 书名:《聪明的投资者》&…...

TypeScript声明文件

TypeScript声明文件 在JavaScript的生态系统中,随着项目的复杂度和规模不断增加,开发者对于类型安全和代码质量的追求也日益增长。TypeScript,作为JavaScript的一个超集,通过添加静态类型检查和ES6等新特性支持,极大地…...

.NET_WPF_使用Livecharts数据绑定图表

相关概念 LiveCharts 是一个开源的图表库,适用于多种 .NET 平台,包括 WPF、UWP、WinForms 等。LiveCharts 通过数据绑定与 MVVM 模式兼容,使得视图模型可以直接控制图表的显示,无需直接操作 UI 元素。这使得代码更加模块化&#x…...

一句JS代码,实现随机颜色的生成

今天我们只用 一句JS代码,实现随机颜色的生成,首先看一下效果: 每次刷新浏览器背景颜色都不一样 实现此效果的JS函数 : let randomColor () > ...: 定义一个箭头函数randomColor,用于生成一个随机颜色。 Math.ra…...

校园抢课助手【7】-抢课接口限流

在上一节中,该接口已经接受过风控的处理,过滤掉了机器人脚本请求,剩下都是人为的下单请求。为了防止用户短时间内高频率点击抢课链接,海量请求造成服务器过载,这里使用接口限流算法。 先介绍下几种常用的接口限流策略…...

char类型和int类型

一、char类型 在Java中,char(字符)类型用于表示单个字符,它是基本数据类型之一。以下是关于Java中char类型的一些重要信息: 表示方式: char类型用于存储Unicode字符,占用16位(即2个字…...

C++参悟:stl中的比较最大最小操作

stl中的比较最大最小操作 一、概述二、最小值1. min2. min_element 三、最大值1. max2. max_element 四、混合1. minmax2. minmax_element 一、概述 记录这里C11中常用的最小值和最大值的比较函数,最好的参考资料其实就是 https://zh.cppreference.com 最重要的查…...

JAVA读取netCdf文件并绘制热力图

读取netCdf的依赖 <dependency><groupId>ucar</groupId><artifactId>netcdfAll</artifactId><version>5.5.3</version><scope>system</scope><exclusions><exclusion><groupId>org.slf4j</groupId…...

数据结构——八大排序

一.排序的概念和其应用 1.1排序的概念 排序&#xff1a;排列或排序是将一组数据按照一定的规则或顺序重新组织的过程&#xff0c;数据既可以被组织成递增顺序&#xff08;升序&#xff09;&#xff0c;或者递减顺序&#xff08;降序&#xff09;。稳定性&#xff1a;假定在待…...

【Unity】RPG2D龙城纷争(十九)流程与UI界面(终章)

更新日期:2024年8月1日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、游戏流程1.初始化流程2.开始流程3.关卡流程4.关卡结束流程5.启用所有流程二、UI界面逻辑1.开始界面2.存档界面3.关卡界面DataRegion 数据显示逻辑区域RoundRegion 回合逻辑区域RoleMenu…...

C#类和结构体的区别

1、类class是引用类型&#xff0c;多个引用类型变量的值会互相影响。存储在堆&#xff08;heap&#xff09;上 2、结构体struct是值类型&#xff0c;多个值类型变量的值不会互相影响。存储在栈&#xff08;stack&#xff09;上 类结构关键字classstruct类型引用类型值类型存储…...

【RabbitMQ】RabbitMQ持久化

一、简介 RabbitMQ的持久化机制是一种确保数据在RabbitMQ服务重启或异常情况下不会丢失的重要特性。RabbitMQ的持久化主要包括三个方面的内容&#xff1a;交换器的持久化、队列的持久化、消息的持久化。 二、交换器的持久化 1、实现方式 在RabbitMQ中&#xff0c;实现交换器…...

算法刷题笔记 Kruskal算法求最小生成树(详细算法介绍,详细注释C++代码实现)

文章目录 题目描述基本思路实现代码 题目描述 给定一个n个点m条边的无向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。求最小生成树的树边权重之和&#xff0c;如果最小生成树不存在则输出impossible。 最小生成树的概念&#xff1a;给定一张边带权的无向…...

5年经验的软件测试人员,碰到这样的面试题居然会心虚......

我们这边最近的面试机会比较多&#xff0c;但是根据他们的反馈&#xff0c;结束后大部分都没音信了&#xff0c;因为现在企业面试问的非常多&#xff0c;范围非常广&#xff0c;而且开放性的问题很多&#xff0c;很多人即便面试前刷了成百上千道面试题&#xff0c;也很难碰到一…...

C#进阶-轻量级ORM框架Dapper的使用教程与原理详解

本文详细介绍了Dapper在C#中的使用方法&#xff0c;包括Dapper的基本概念、与其他持久层框架的比较、基本语法和高级语法的使用&#xff0c;并通过实例讲解了如何在项目中集成和使用Dapper。Dapper以其高效的性能和简洁的API受到开发者的青睐&#xff0c;适用于各种数据库操作需…...

Windows图形界面(GUI)-MFC-C/C++ - 编辑框(Edit Control) - CEdit

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 编辑框(Edit Control) - CEdit 基本概念 成员函数 示例代码 编辑框(Edit Control) - CEdit 基本概念 编辑框&#xff08;Edit Control&#xff09;是一个允许用户输入和编辑文本的窗…...

网络安全防御【IPsec VPN搭建】

目录 一、实验拓扑图 二、实验要求 三、实验思路 四、实验步骤&#xff1a; 修改双机热备的为主备模式&#xff1a; 2、配置交换机LSW6新增的配置&#xff1a; 3、防火墙&#xff08;FW4&#xff09;做相关的基础配置&#xff1a; 4、搭建IPsec VPN通道 &#xff08;1…...

5步构建智能医疗预约系统:91160-cli全流程实战指南

5步构建智能医疗预约系统&#xff1a;91160-cli全流程实战指南 【免费下载链接】91160-cli 健康160全自动挂号脚本 项目地址: https://gitcode.com/gh_mirrors/91/91160-cli 医疗资源紧张导致的挂号难题&#xff0c;让无数患者在凌晨守候却依然一号难求。如何突破人工抢…...

从g2o优化框架看TEB算法:手撕局部路径规划的图优化实现

从g2o优化框架看TEB算法&#xff1a;手撕局部路径规划的图优化实现 在机器人导航领域&#xff0c;局部路径规划算法的性能直接决定了机器人在动态环境中的反应速度和避障能力。TEB&#xff08;Timed Elastic Band&#xff09;算法作为ROS生态中广泛采用的解决方案&#xff0c;其…...

GT IP跑Aurora 64B66B协议:从变速箱到加扰的实战避坑指南

GT IP实现Aurora 64B66B协议&#xff1a;从变速箱到加扰的工程实践全解析 在高速串行通信领域&#xff0c;Xilinx的GT系列IP核配合Aurora 64B66B协议已成为许多硬件工程师的首选方案。这种组合能够提供高达数十Gbps的数据传输速率&#xff0c;广泛应用于数据中心互连、高性能计…...

全球协作的终极指南:Open Library多语言团队开发与维护的最佳实践

全球协作的终极指南&#xff1a;Open Library多语言团队开发与维护的最佳实践 【免费下载链接】openlibrary One webpage for every book ever published! 项目地址: https://gitcode.com/gh_mirrors/op/openlibrary Open Library是一个致力于为每一本已出版书籍创建网页…...

vLLM-v0.17.1部署教程:vLLM+NGINX实现SSL/TLS加密API服务

vLLM-v0.17.1部署教程&#xff1a;vLLMNGINX实现SSL/TLS加密API服务 1. vLLM框架简介 vLLM是一个专注于大语言模型(LLM)推理和服务的高性能开源库。它最初由加州大学伯克利分校的天空计算实验室开发&#xff0c;现已发展成为一个由学术界和工业界共同维护的社区项目。 这个框…...

别光重启!Ping域名失败但nslookup能通?一个注册表键值引发的血案(附排查脚本)

当Ping域名失败但nslookup正常&#xff1a;深入解析Windows注册表键值缺失的连锁反应 那天凌晨三点&#xff0c;运维工程师李明在机房盯着屏幕&#xff0c;额头渗出细密的汗珠。客户的核心业务系统刚刚完成迁移&#xff0c;却在最后验收阶段出现诡异现象——所有服务器都能通过…...

从CTF逆向实战出发:手把手教你用Python脚本破解RC4和Base58加密(附完整代码)

从CTF逆向实战出发&#xff1a;手把手教你用Python脚本破解RC4和Base58加密&#xff08;附完整代码&#xff09; 在CTF竞赛中&#xff0c;逆向工程题目往往涉及各种加密算法的识别与破解。本文将聚焦两种常见加密方式——RC4和Base58&#xff0c;通过Python脚本实现从算法识别到…...

深度拆解 JDK1.8 ConcurrentHashMap 核心方法:从 put 到扩容,彻底吃透并发神器

在 Java 高并发编程中&#xff0c;ConcurrentHashMap是线程安全 Map 的绝对首选&#xff0c;而 JDK1.8 版本对它的重构堪称并发设计的巅峰之作 —— 彻底抛弃分段锁&#xff0c;用CAS 桶级 synchronized实现极致细粒度并发&#xff0c;搭配多线程协同扩容、链表红黑树转换、高…...

动态规划专练:力扣第509、70、746题

由于对动态规划DP算法 掌握得不是很好&#xff0c;所以决定进行动态规划专项训练。动态规划五部曲①确定dp[i]含义②递推公式③dp数组如何初始化④遍历顺序⑤打印dp数组&#xff08;debug&#xff09;除了第五条在力扣上不开会员无法实现外&#xff0c;其余四项就是做出dp类型题…...

InfluxDB服务文件被误删怎么办?记录一次完整的1.8.6版本灾难恢复过程

InfluxDB服务文件误删灾难恢复实录&#xff1a;从崩溃边缘到完美复原 那天下午&#xff0c;服务器监控大屏突然亮起一片刺眼的红色告警——InfluxDB服务全线离线。作为团队里负责时序数据库运维的老兵&#xff0c;我立刻意识到问题的严重性。这套运行着1.8.6版本的InfluxDB承载…...