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

【Linux庖换现象丁解牛】—进程程序替换!

1. 进程程序替换现象

我们先直接见一下进程程序替换的现象,至于下面我用到的函数我们暂时不用管理解。

#include <unistd.h>
#include <stdio.h>int main()
{printf("程序开始运行\n");execl("/usr/bin/ls","ls","-a","-l",NULL);                                                                                                   printf("程序运行完毕\n");return 0;
}

 我们用进程./code执行了系统级指令ls,这种现象就是进程程序替换,当然我们还可以替换其他指令!

  2. 进程程序替换原理

我们观察上面的运行结果也会发现,进程发生程序替换后,进程运行的结果并没有【程序运行完毕】这个字符串,但是,在我们的代码中实际上是会打印这个字符串的!这就和进程程序替换的原理有关了:当我们调用了exec*系列的接口后,如果进程替换成功,那么原代码就会被替换进程的代码覆盖【也就是说原代码已近不存在了】。所以只要进程程序替换成功,无论之后我们写了什么代码,我们都不会执行了。

其实,如果进程替换失败,会返回-1值。

可是,如果我们不希望进程程序替换影响我们的原进程,怎么办呢?

很简单,我们仅需要创建一个子进程,用子进程来替换【代码和数据】。至于为什么这样做不会影响父进程:从宏观上来讲,进程具有独立性。具体一点的话,子进程的代码发生改变,那子进程也会发生写实拷贝【这和我们之前说过的数据改变发生写实拷贝的 原理相同】。既然如此,那我们也必须注意到一点,进程程序替换并没有创建一个新的进程,而只是改变了原进程中的代码,代码可能会更多,对应的地址映射可能也会发生改变,但这些我们并不关心。

那execl除了可以替换系统级的可执行程序,能不能替换我们自己写的程序呢!答案是肯定的。简单演示一下:

下面我在当前目录下写了一个C++程序,并在C程序中调用了该程序!

那该接口是否可以调用python语言呢?当然可以,不止如此,无论是脚本语言,还是编译型,解释型等等,只要在系统下执行,他都会最终变成一个进程加载到内存中。而exec*系列的接口是系统级别的,所以可以调用各种语言编写的程序!

3. exec*系列接口

接下来我们就来理解一下exec*系列接口。

首先就是我们刚刚用到的execl:

它的第一个参数就是路径,第二个参数是程序名称,我们注意到后面的三个...,在C语言中我们就知道这是可变参数【这部分参数的填写原则就是:指令怎么敲,参数怎么填】,不过,我们要最后填写一个NULL参数表明参数填写完毕!(l就是list的意思,表示参数列表)

execlp:

p即PATH环境变量,该接口在我们替换系统级指令时比较方便,因为我们仅需填写指令名,该接口就会自动去环境变量PATH指定的路径下去找!

execv:

v即vector,我们可以简单的理解为数组,第一个参数也是传路径,后面我们需要传一个命令行参数表,即指针数组,下面演示一下:

 execvpe:

e即是environment,环境变量的意思。如果我们使用子进程用该接口进行程序替换,并且我们还传递了新的环境变量,那么子进程实际上就被要求使用全新的环境变量,子进程从bash中继承的旧环境变量全部被覆盖,而不是新增!下面就举一个栗子理解一下:

我们先写一个other程序,这个程序会打印自己的命令行参数表和环境变量表:

 接下来,我们在code.c中创建子进程,使用execvpe接口用other替换该子进程。并且我们传递自己写的命令行参数表和环境变量表,看看结果。

实验和我们预期的一样,但是,如果我们想新增环境变量,保留原来的,我们要如何办到呢?

第一个做法就是不使用execvpe接口,我们使用其他接口配合putenv()接口就可以办到。

 谁【进程】调用该接口导入环境变量,谁的环境变量表中就会新增自己写的环境变量!

那如果我非要用带e系列的接口,我该怎么办到呢?

其实也非常简单,既然我们传递的环境变量表是覆盖式的,那我们将environ传过去不就行了吗。在这之前,我们把自己写的环境变量用putenv提前导入不就行了吗!

http://www.xdnf.cn/news/572779.html

相关文章:

  • python训练营打卡第30天
  • C++--string类对象
  • 【ffmpeg】ffprobe基本用法
  • 想解决内容同质化难题?运营该从哪入手?
  • linux系统查看硬盘序列号
  • 129.在 Vue3 中使用 OpenLayers 实现点击获取重叠要素信息(支持多 Feature)
  • Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解
  • ES的倒排索引和正排索引的区别及适用场景?为什么倒排索引适合全文搜索?
  • 目标检测基础知识
  • 使用 electron-builder 打包与发布 Electron 应用
  • Prometheus+Grafana实现对服务的监控
  • 黑色矩形大于6识别
  • RTMP协议解析【二】
  • RTMP协议解析[一]
  • lcd气压表研发方案芯片——用于胎压检测
  • Ubuntu 20.04安装及配置docker
  • 进程调度算法深度剖析:FCFS、SJF、RR、优先级及多级反馈队列全解
  • 算法第25天 | 491. 非递减子序列、46. 全排列、47. 全排列 II
  • Java 实现二进制与十进制之间的互相转换
  • 校平机的原理、应用及发展趋势
  • Vue3学习(Vue3.3新特性——defineModel宏详解)
  • OpenCv高阶(十六)——Fisherface人脸识别
  • MySQL 索引的增删改查
  • Docusaurus Umami
  • 算法优选系列(9.BFS 解决拓扑排序)
  • GStreamer (四)交叉编译
  • 华为eNSP无线AC/AP组网实战
  • 基于大模型的闭合性尺桡骨干骨折全方位诊疗研究报告
  • 现代计算机图形学Games101入门笔记(二十)
  • V少JS基础班之第五弹