Linux —— 进程的程序替换[进程控制]
🎁个人主页:工藤新一¹
🔍系列专栏:C++面向对象(类和对象篇)
🌟心中的天空之城,终会照亮我前方的路
🎉欢迎大家点赞👍评论📝收藏⭐文章
文章目录
- 进程的程序替换[进程控制]
- 一、替换原理
- 二、替换函数(接口)
- 2.1 函数解释
- 2.2命名理解
进程的程序替换[进程控制]
一、替换原理
进程程序替换的核心原理是:保持进程结构不变,只替换进程的内存映像,使得同一个进程可以执行不同的程序代码(允许一个正在运行的进程 完全“变身”为另一个程序)
程序替换,顾名思义,就是将一个进程当前正在运行的程序(代码、数据、堆栈等)全部替换掉,转而执行一个全新的、磁盘上的程序文件。
这个过程的特点是:
- 并非创建新进程:进程的PID、父进程号、打开的文件描述符表等属性保持不变。它还是原来的那个进程,“壳”没变,但“芯”完全换了。
- 旧代码被覆盖:当前进程的正文段(代码)、数据段、堆栈段等存储空间会被新程序的相应部分覆盖。
- 从 main 开始:新程序会从它的
main
函数开始执行。
在 Linux/Unix 系统中,这一功能是通过 exec
系列函数族(如 execve
, execl
, execvp
等)来实现的。
换句话说:一旦替换成功,程序的后半段源代码是不会被执行的
可以得出结论:exec* 系列的函数,无需做返回值判断,因为只要返回就是失败!
二、替换函数(接口)
其实有六种以 exec
开头的函数,统称exec函数:
2.1 函数解释
- 这些函数如果调⽤成功则加载新的程序从启动代码开始执⾏,不再返回。
- 如果调⽤出错则返回-1
- 所以exec函数只有出错的返回值⽽没有成功的返回值
2.2命名理解
这些函数原型看起来很容易混,但只要掌握了规律就很好记:
- l(list) : 表⽰参数采⽤列表
- v(vector) : 参数⽤数组
- p(path):有p⾃动搜索环境变量PATH
- e(env):表⽰⾃⼰维护环境变量
接口 - execl();
加载器:
使用 C程序 调用 C++程序:
一切可转化为进程运行的程序,全都能够被替换
验证:程序替换不会创建新的进程
在使用上只是传参形式不同
今天是子进程调用 execv();我们知道:每一进程都存在命令行参数(argc, argv),所以我们曾经并不知道我们自己进程的命令行是谁传入的?如何传入的?
答:子进程调用 exec* 时,如果存在命令行参数(argv),就将 argv
通过 execv()
传给进程(“ls”)
所有程序在运行时,都是 bash 的子进程;子进程的命令行参数来源于其父进程通过 exec() 系统调用传的
execvpe()
现象:替换 进程中历史[argv[] & env[]
]列表被子进程列表完全覆盖掉
execvp()
现象:新增[不覆盖] 环境变量
putenv();
使进程直接获得环境变量:
增量式的添加环境变量:
- 直接 putenv();
- (exec e, putenv(), environ);*
自带 ‘e’ 的系统调用会默认替换掉环境参数列表中环境变量
environ - 默认环境变量的起始地址
进程替换的本质:让进程执行全新的 代码 & 数据[程序]
为什么要做语言级别的封装呢:在做程序替换时,我们要面对各种各样不同的上层替换所需的场景。将这些接口丰富多样起来,未来调用时所有信息的处理会将这些传参统一转化为系统调用 execve();的样子,方便我们使用
特性 | 描述 |
---|---|
是什么 | 一个进程保持其PID不变,将其内存映像完全替换为另一个程序代码的过程。 |
怎么做 | 通过 exec 系列函数(如 execve ) 实现。通常与 fork 结合使用。 |
为什么需要 | 高效(利用写时复制)、灵活(创建与执行解耦,便于中间设置)、管理方便(维持清晰的进程关系)。 |
主要用途 | Shell执行命令、启动应用程序、运行脚本、服务器处理请求、权限控制等。 |
简单来说,程序替换是操作系统提供的一种“金蝉脱壳”的能力,让一个进程能够华丽转身,去执行一个全新的使命,而无需“重新投胎”(创建新进程)
🌟 各位看官好,我是工藤新一¹呀~
🌈 愿各位心中所想,终有所致!