> 文章列表 > 【云原生】Linux进程控制(进程程序替换)

【云原生】Linux进程控制(进程程序替换)

✨ 你知道吗?Linux中的进程,就像是一辆灵活的汽车,随时可以更换“轮胎”来应对不同的任务!所谓“程序替换”,就是让子进程像换轮胎一样,替换成其他程序来完成特定任务😀

比如,当你在bash shell中输入ls命令时,bash就会创建一个子进程,然后把这个子进程换成ls命令程序,帮你列出文件列表。这就好比你开车去越野时,换成专业的越野胎一样🏂

但是,万一程序替换失败了呢?比如你试图启动一个不存在的程序,那这个子进程就会“罢工”啦!这时候就需要检查错误原因,比如路径是否正确、权限是否足够等等🤖

你还能想到哪些场景需要“进程替换”呢?比如在服务器上同时运行多个服务,或者在程序中动态加载不同的插件,这些都需要用到类似的思想哦!🙊

【云原生】Linux进程控制(进程程序替换)

✨个人主页: Yohifo
🎉所属专栏: Linux学习之旅
🎊每篇一句: 图片来源
🎃操作环境: CentOS 7.6 阿里云远程服务器

  • Good judgment comes from experience, and a lot of that comes from bad judgment.
    • 好的判断力来自经验,其中很多来自糟糕的判断力。

上帝的指纹


文章目录

  • 🌇前言
  • 🏙️正文
    • 1、为何要进行程序替换?
    • 2、七大替换函数
      • 2.1、函数1 execl
      • 2.2、函数2 execv
      • 2.3、函数3 execlp
      • 2.4、函数4 execvp
      • 2.5、函数5 execle
      • 2.6、函数6 execve
      • 2.7、函数7 execvpe
    • 3、补充
      • 3.1、函数名记忆
      • 3.2、替换现象
  • 🌆总结

🌇前言

子进程 在被创建后,共享的是 父进程 的代码,如果想实现自己的逻辑就需要再额外编写代码,为了能让 子进程 执行其他任务,可以把当前 子进程 的程序替换为目标程序,此时需要用到 Linux 进程程序替换相关知识

子进程 替换为其他程序后,无法再执行原有程序,但 进程 始终为同一个

火爆全网的 ChatGTP 能否替换 “人类” ?

机器人


🏙️正文

1、为何要进行程序替换?

在学习相关函数前,先要弄清楚为何要进行程序替换?

  • 将运行中的程序看作一个 任务处理平台
  • 由我们发出指令,交给 任务处理平台 去完成
  • 因为每次发出的指令都可能不相同,所以 任务处理平台 中的代码不能固化
  • 为了解决这个问题,任务处理平台 可以通过创建子进程,让子进程完成对应指令
  • 子进程实现对应指令依赖于程序替换

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

就像汽车拥有各种各样的轮胎,如越野时需要换上路面兼容性更好、更耐造的越野胎;日常家用时,舒适性更好、胎噪更小的轮胎显然就更合适了,针对不同的使用场景替换不同的轮胎,程序替换时也是这么个意思,执行特定任务

轮胎分类
shell 外壳中的 bash 就是一个任务处理平台,当我们发出指令,如 lspwdtouch 等指令时后,bash 会创建子进程,将其替换为对应的指令程序并执行任务,就能实现各种指令

bash

进程程序替换图解

  • Linux 中的指令都是用 C语言 写的可执行程序,所以可以进行替换
  • bash 运行后,输入 指令 本质上就是在进行程序替换

进程替换

关于简易版 bash 的实现方法,将在下篇文章中揭晓


2、七大替换函数

进程程序替换函数共有七个,其中六个都是在调用函数6,因此函数6 execve 才是真正的系统级接口

函数介绍

各种替换函数间的关系

函数调用关系
这些函数都属于 exec 替换家族,所以它们的返回值都一样

注意: 这七个函数只有在程序替换失败后才会有返回值,返回 -1,程序替换成功后不返回

程序都已经替换成功,后续代码也都将被替换,所以成功后的返回值也就没意义了

2.1、函数1 execl

首先是最简单的替换函数 execl

#include <unistd.h>int execl(const char* path, const char* arg, ...);

函数解读

  • 返回值:替换失败返回 -1
  • 参数1:待替换程序的路径,如 /usr/bin/ls
  • 参数2:待替换程序的名称,如 ls
  • 参数3~N:待替换程序的选项,如 -a -l等,最后一个参数为 NULL,表示选项传递结束
  • ... 表示可变参数列表,可以传递多个参数

图解

注意: 参数选项传递结束或不传递参数,都要在最后加上 NULL,类似于字符串的 '\\0'

#include <stdio.h>
#include <unistd.h>int main()
{//execl 函数printf("程序替换前,you can see me\\n");int ret = execl("/usr/bin/ls", "ls", "-a", "-l", NULL);//程序替换多发生于子进程,也可以通过子进程的退出码来判断是否替换成功