Linux--进程控制(2)--进程的程序替换(夺舍)

2024-04-27 14:12

本文主要是介绍Linux--进程控制(2)--进程的程序替换(夺舍),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

进程的程序替换

0.相关函数

1.先看现象

 2.解释原理

3.将代码改成多进程版

 4.使用其它的替换函数,并且认识函数参数的含义

5.其它


进程的程序替换


0.相关函数

 关于进程替换我们需要了解的6个函数:

函数解释:

  • 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
  • 如果调用出错则返回-1
  • 所以exec函数只有出错的返回值而没有成功的返回值

命名理解:

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

exec调用举例如下:

int main()
{char* const argv[] = { "ps", "-ef", NULL };char* const envp[] = { "PATH=/bin:/usr/bin", "TERM=console", NULL };execl("/bin/ps", "ps", "-ef", NULL);// 带p的,可以使用环境变量PATH,无需写全路径execlp("ps", "ps", "-ef", NULL);// 带e的,需要自己组装环境变量execle("ps", "ps", "-ef", NULL, envp);execv("/bin/ps", argv);// 带p的,可以使用环境变量PATH,无需写全路径execvp("ps", argv);// 带e的,需要自己组装环境变量execve("/bin/ps", argv, envp);exit(0);
}

      

1.先看现象

先来看一段代码:

运行结果:我们发现让程序使用exec*函数,可以执行起来新的程序

我们还发现,执行玩这条语句,后面的语句都不执行了


 2.解释原理

我们都知道,我们的可执行程序运行起来就变成了进程。

创建进程=创建内核相关管理的数据结构(task_struct,mm_struct,页表)+代码和数据。

        内存管理的数据,如代码段、数据段和堆栈等,则包含了程序执行所需的数据和代码。

        当我们谈论进程替换时,实际上是指用一个新的程序来完全替代当前进程的内存映像,也就是替换掉原有的代码段、数据段和堆栈等内存管理的数据。而CPU执行的上下文,如程序计数器、寄存器和程序状态字等,则会被新的程序所继承。这样,新的程序就可以从它的入口点开始执行,就像它是一个全新的进程一样。(但他不是一个全新的程序,因为这个过程并没有创建新的进程,只是替换掉了原进程的数据和代码,依旧使用原来进task_struct,mm_struct,页表) 用老进程的壳子执行新的代码和数据。(可以理解成被夺舍了)

        exec*函数族就是用来实现这种进程替换的系统调用。这些函数会根据指定的文件名找到可执行的文件,并用它来替换当前进程的内容。换句话说,它们会在当前进程内部执行一个全新的可执行文件。

 当你调用一个exec*函数时,它会做以下几件事情:

  1. 查找并加载新的程序文件到内存。
  2. 清除当前进程的内存映像,包括代码段、数据段和堆栈等。
  3. 将新的程序的代码和数据加载到当前进程的内存空间中。
  4. 更新程序计数器,使其指向新程序的入口点。
  5. 开始执行新程序。       

        值得注意的是,exec*函数执行成功就不需要关心它的返回值了。这是因为调用进程的实体,包括代码段、数据段和堆栈等,都已被新的内容所取代,只留下进程ID等一些表面上的信息保持原样。所以,一旦exec*函数执行成功,当前进程就已经被新的程序所替代,原有的程序已经不再存在。(这就是为什么在上面执行那段代码的时候,程序最后没有执行printf("test .... end!\n");)

        总的来说,exec*函数族是Linux环境下实现进程替换的重要工具。它们通过替换当前进程的内存映像来执行新的程序,使得我们可以在一个进程中执行不同的程序,从而实现程序的切换和执行流程的改变。
 


3.将代码改成多进程版

        我想进行程序替换,但我不想影响我父进程本身,这时候我们就可以把代码改成多进程版本,让子进程去进行替换,父进程进行wait就行了。

代码示例:

运行结果:


 4.使用其它的替换函数,并且认识函数参数的含义

int execl(const char *path, const char *arg, ...);

path : 我们要执行程序,需要带路径(怎么找到程序,你得告诉我)(你想执行谁)

list列表:在命令中怎么执行,就这么传参(标准情况)(你想怎么执行)

int execv(const char *path, char *const argv[])
path :和上面的一样

argv:是一个指针数组,直接把参数传到数组里

用法:

int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);

p:用户可以不传要执行的文件路径(但是要穿文件名),查找这个程序,系统会自动在环境变量PATH中进行查找。

用法:

int execle(const char *path, const char *arg, ...,char *const envp[]);
int execvpe(const char *path, char *const argv[], char *const envp[]);

这里的e:表示环境变量(environment)

上面的程序替换,我们替换的都是系统命令,可不可以替换我们自己的程序呢?

这是我们在C语言程序调用C++程序的方式

我们在C++程序中写的

编译c和c++程序运行c程序:我们成功的替换了我们自己的程序

接着谈环境变量。接上面代码:这一次我们将环境变量给了execvpe函数

我们在c++程序中接收了,命令行参数表和环境变量表并将它们打印出来了:

编译运行看一下效果:

结论:我们平时自己运行的程序,命令行参数和环境变量,是父进程通过将自己的环境变量表和命令行参数表通过,execvpe函数传递来的。而我的父进程本身就有一批环境变量!!从bash来。(我们是可以将bash的环境变量表直接传给子进程的,就不做演示了)。


5.其它

         事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve,所以execve在man手册 第2节,其它函数在man手册第3节。这些函数之间的关系如下图所示。

下图exec函数族 一个完整的例子:

这篇关于Linux--进程控制(2)--进程的程序替换(夺舍)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940713

相关文章

Linux中shell解析脚本的通配符、元字符、转义符说明

《Linux中shell解析脚本的通配符、元字符、转义符说明》:本文主要介绍shell通配符、元字符、转义符以及shell解析脚本的过程,通配符用于路径扩展,元字符用于多命令分割,转义符用于将特殊... 目录一、linux shell通配符(wildcard)二、shell元字符(特殊字符 Meta)三、s

Linux之软件包管理器yum详解

《Linux之软件包管理器yum详解》文章介绍了现代类Unix操作系统中软件包管理和包存储库的工作原理,以及如何使用包管理器如yum来安装、更新和卸载软件,文章还介绍了如何配置yum源,更新系统软件包... 目录软件包yumyum语法yum常用命令yum源配置文件介绍更新yum源查看已经安装软件的方法总结软

linux报错INFO:task xxxxxx:634 blocked for more than 120 seconds.三种解决方式

《linux报错INFO:taskxxxxxx:634blockedformorethan120seconds.三种解决方式》文章描述了一个Linux最小系统运行时出现的“hung_ta... 目录1.问题描述2.解决办法2.1 缩小文件系统缓存大小2.2 修改系统IO调度策略2.3 取消120秒时间限制3

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

Linux:alias如何设置永久生效

《Linux:alias如何设置永久生效》在Linux中设置别名永久生效的步骤包括:在/root/.bashrc文件中配置别名,保存并退出,然后使用source命令(或点命令)使配置立即生效,这样,别... 目录linux:alias设置永久生效步骤保存退出后功能总结Linux:alias设置永久生效步骤

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

LinuxMint怎么安装? Linux Mint22下载安装图文教程

《LinuxMint怎么安装?LinuxMint22下载安装图文教程》LinuxMint22发布以后,有很多新功能,很多朋友想要下载并安装,该怎么操作呢?下面我们就来看看详细安装指南... linux Mint 是一款基于 Ubuntu 的流行发行版,凭借其现代、精致、易于使用的特性,深受小伙伴们所喜爱。对