【Linux】进程的程序替换(execl、execlp、execle、execvpe等替换函数)

news2025/1/16 2:34:03

文章目录

    • 1、进程程序替换
      • 1.1 理解进程替换原理
      • 1.2 进程相应替换函数
      • 1.3 进一步理解程序替换

1、进程程序替换

父进程创建子进程的目的:
1.想让子进程执行父进程代码的一部分。(子承父业)
2.想让子进程执行一个全新的程序。

进程程序替换讨论的就是子进程执行一个全新程序的情况。

1.1 理解进程替换原理

进程替换主要是通过调用库函数中众多exec类函数来实现的。
首先让我们来看看其中最简单的

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

将指定的程序加载到内存中,让指定进程进行执行。
其中
path:是如何找到程序的路径
arg:是可变参数列表:arg[0]、arg[1]、arg[2],最后一个跟NULL结束

返回值:函数调用失败返回-1,成功的返回值没有意义。
如:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main()
  5 {
  6     printf("process is running...\n");
  7     execl("/usr/bin/ls", "ls", "--color=auto", "-a", "-l", NULL);
  8     printf("process running done...\n");                                                                                                            
  9                                                                                                                                          
 10     return 0;                                                                                                                            
 11 }

在这里插入图片描述
只允许第一行打印,随后执行对应命令,进程代码被替换最后一行不打印,结果没错。

进程替换原理也其实很简单,就是将原来进程数据代码内容给替换了
在这里插入图片描述

1.2 进程相应替换函数

下面对应进程替换函数都属于前缀exec的

首先看exec中列表类的,命名理解:

  • -l 代表列表(对于arg,得写多个参数)
  • -p 代表文件名 (相对于path,可以直接通过文件名在环境变量中找程序)
  • -e 代表环境变量 (可以给替换的程序自己组环境变量)
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char* const envp[]);

execlp只需要修改路径为程序名。

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main()
  5 {
  6     printf("process is running...\n");
  7     execlp("ls", "ls", "--color=auto", "-a", "-l", NULL);                                                                                           
  8     printf("process running done...\n");
  9 
 10     return 0;
 11 }

execle需要自己指定环境变量,如果不写默认继承进程的环境变量。

//mybin.c中
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 int main()
  5 {
  6     printf("PATH:%s\n", getenv("PATH"));
  7     printf("PWD:%s\n", getenv("PWD"));
  8     printf("MYENV:%s\n", getenv("MYENV"));                                                                                                          
  9     return 0;
 10 }
//myexe.c中
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main()
  5 {
  6     char* const envp_[] = {(char*)"MYENV=12235", NULL};
  7     execle("./mybin", "mybin", NULL, envp_);
  8     return 0;                                                                                                                                       
  9 }

在这里插入图片描述
可以看到,这里替换成了自己写的mybin程序,并且指定了自己组装envp_环境变量。

除了列表类的,还是数组类的。

exec中数组类的,命名理解:

  • -v 代表数组
  • -p 代表文件名 (相对于path,可以直接通过文件名在环境变量中找程序)
  • -e 代表环境变量 (可以给替换的程序自己组环境变量)
#include <unistd.h>
int execv(const char *path, char* const argv[]);
int execvp(const char *file, char* const argv[]);
int execvpe(const char *path, char* const argv[], char* const envp[]);

例子:

//mybin.c
    1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <string.h>
    4 
    5 int main(int argc, char* argv[])
    6 {
    7     printf("PATH:%s\n", getenv("PATH"));
    8     printf("PWD:%s\n", getenv("PWD"));
    9     printf("MYENV:%s\n", getenv("MYENV"));
   10 	 
   11     if(strcmp(argv[1], "-t") == 0)                                                                                                                
   12     {
   13         printf("使用了-t\n");
   14     }
   15     return 0;
   16 }


//myexec.c
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/wait.h>
  5 #include <assert.h>
  6 
  7 int main()
  8 {
  9     printf("process is running...\n");
 10     pid_t id = fork();
 11     assert(id != -1);
 12 
 13     if(id == 0)
 14     {
 15         extern char** environ;
 16         char* const myargc_[] = {(char*)"mybin", (char*)"-t", NULL}; //自己组建命令行参数
 17         execvpe("./mybin", myargc_, environ);   //调用继承的环境变量                                                                                                    
 18         exit(1);  //mush failed
 19     }
 20 
 21     int status = 0;
 22     pid_t ret = waitpid(id, &status, 0);
 23     if(ret > 0)
 24     {
 25         printf("wait success: exit code: %d, sig: %d\n", (status>>8)&0xFF, status & 0x7F);
 26     }
 27     return 0;

在这里插入图片描述

如果我们即想用系统的环境变量,又想用自己的怎么办?
通过putenv(),将定义的环境变量加入到系统中,environ指向的表。

#include <stdlib.h>
int putenv(char* string);
//通过在之前代码中加入putenv
 15         extern char** environ;
 16         char* const myargc_[] = {(char*)"mybin", (char*)"-t", NULL};
 17         putenv("MYENV=1234");                                                                                                                       
 18         execvpe("./mybin", myargc_, environ);                                                                       
 19         exit(1);  //mush failed 

在这里插入图片描述

1.3 进一步理解程序替换

通过以上知道了,系统通过exec系列的函数,将硬盘中的程序替换到内存中。程序加载到内存中,这是体系结构规定的,很好理解。

那么回到main函数.

int execve(const char* filename, char* const argv[], char* const envp[]);

int main(int argc, char* argv[], char* env[]);

其实,在main函数被调用之前,先加载了exec系列中的函数,并且main中的参数其实也是由exec函数加载的。

最后一个
通过man 3 exec库函数手册可以看到这些,但似乎少了一个execve。
在这里插入图片描述

再通过man 2 execve 系统手册可以看到它
在这里插入图片描述
其实execve才是真正的系统调用,其它的都是通过它的封装,为了给我们满足多种应用场景的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深圳大学数学文化赏析MOOC第一次作业答案(满分)

一、单选题 (共 40.00 分) 1. 关于归纳推理&#xff0c;以下说法错误的是 A. 归纳推理是从特殊到一般的推理。 B. 归纳推理属于发散性思维。 C. 归纳推理的结论一定是正确的。 D. 归纳推理具有创新性。 满分&#xff1a;2.00 分 得分&#xff1a;2.00 分 你的答案&a…

[MySQL]-数据库恢复工具之binlog2sql

[MySQL]-数据库恢复工具之binlog2sql 森格 | 2022年12月 本文主要介绍工具binlog的使用&#xff0c;它可以帮助我们快速解析出原始SQL、回滚SQL、去除主键的INSERT SQL等。 一、工具介绍 1.1 概述 我们可以去设想&#xff0c;当开发人员使用了delete语句误删除了某表的数据&…

微服务实用篇5-分布式搜索elasticsearch篇1

今天的主要学习任务是分布式搜索&#xff0c;首先了解elasticsearch&#xff0c;然后学习索引库的操作、文档的操作、RestAPI等。elasticsearch是非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速定位到我们需要的内容。这一篇主要学习ES的基本使用&#xff0c…

rocketmq源码-关于消费者push模式和pull模式的对比

在rocketmq中&#xff0c;对于消费者而言&#xff0c;有两种模式&#xff0c;push和pull 我在没有看源码之前&#xff0c;看其他博客的时候&#xff0c;大部分的说法是&#xff1a; mq中有两种获取消息的模式&#xff0c;一种是push&#xff0c;一种是pull&#xff1b;pull这种…

技术人员必备的便携版卸载清理工具 - Uninstall Tool 3 便携版直接U盘中启动软件,专为单个用户在多台电脑上使用而设计的。

Uninstall Tool &#xff0c;快速、强大的卸载清理软件&#xff0c;可完全彻底删除已安装软件。彻底删除不需要的应用程序&#xff0c;实时安装监视器。控制在系统启动时运行的应用。有效&#xff0c;强大的应用程序&#xff0c;具有简单而直观的界面。 删除不需要的软件&#…

马斯克都不懂的 GraphQL,API 网关又能对其如何理解?

作者&#xff0c;罗泽轩 上个月马斯克评论 Twitter App 滥用 RPC 后&#xff0c;与一些 Twitter 的技术主管发生了矛盾 —— 直言马斯克不懂技术。那这个马斯克都不懂的 GraphQL 到底是什么&#xff1f; 什么是 GraphQL&#xff1f;它有多流行&#xff1f; GraphQL 是一套由 F…

【javascript】值,类型,变量,函数,noi103题目,if语句,调试

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录基本类型NumberStringboolean例子变量求二元一次方程函数1.3题目if例子1.4题目调试下面我们会随着…

SpringMVC:SpringMVC五种类型参数传递(4)

请求参数1. 环境准备2. 参数传递2.1 GET请求2.1.1 GET发送一个参数2.1.2 GET发送多个参数2.1.3 GET请求中文乱码2.2 POST请求2.2.1 POST发送一个参数2.2.2 POST发送多个参数2.2.3 POST请求中文乱码问题3. 五种类型参数传递3.1 普通参数3.2 POJO类型参数3.3 嵌套POJO类型参数3.4…

HashMap(二)扩容

想要了解HashMap的扩容机制你要有这两个问题 1、什么时候才需要扩容 2、HashMap的扩容是什么 1、什么时候才需要扩容 当HashMap中的元素个数超过数组大小&#xff08;数组长度&#xff09;* loadFactor(负载因子)时&#xff0c;就会进行数组扩容&#xff0c;loadFactor的默认值…

Pytest框架运行常用参数解析

-s&#xff1a;表示输出调试信息&#xff0c;用于显示测试函数中print()打印的信息。我们在用例中加上一句 print(driver.title)&#xff0c;我们再运行一下我们的用例看看&#xff0c;调试信息输出-v&#xff1a;未加前只打印模块名&#xff0c;加v后--verbose打印类名、模块名…

Java中的八大包装类(Wrapper)

目录 一、八大包装类 1、八大包装类的体系图&#xff1a; 二、装箱和拆箱 三、intValue()和valueOf()方法 1、intValue() 2、valueOf() 四、包装类型和String类型的相互转换 五、包装类的常用方法&#xff08;以Integer和Character为例&#xff09; 一、八大包装类 包装…

Scala环境搭建

目录1&#xff09;安装步骤2&#xff09;测试3&#xff09;IDEA安装Scala 插件1&#xff09;安装步骤 1.首先确保 JDK1.8 安装成功 2.下载对应的 Scala 安装文件 scala-2.x.zip 3.解压 scala-2.12.11.zip&#xff0c;我这里解压到 F:\software 4.配置 Scala 的环境变量 …

使用Python和GDAL处理遥感影像数据超详细教程

提示&#xff1a;文章末尾有强化学习代码资源 : ) 前言 在本教程中&#xff0c;我们将学习使用 Python 和地理空间数据抽象库 GDAL 自动处理栅格数据的基本技术。 栅格文件通常用于存储地形模型和遥感数据及其衍生产品&#xff0c;例如植被指数和其他环境数据集。 栅格文件往往…

windows 连接蓝牙耳机失败 解决方法

windows 连接蓝牙耳机失败 解决方法 如果我们在windows7或windows10电脑中连接蓝牙却出现了连接失败的状况&#xff0c;这要怎么办呢&#xff0c;可能是我们没有打开电脑的蓝牙功能&#xff0c;这时我们点击打开蓝牙网络的属性&#xff0c;勾选Bluetooth设置的选项即可&#x…

安卓某通讯协议环境算法浅谈

所有的tlv组包都在 oicq.wlogin_sdk.tlv_type加密算法可以hook oicq.wlogin_sdk.tools Tlv144 是由5个tlv组成 然后用TGTkey进行 TEA加密 tlv_109 AndroidIDtlv_52d 系统内核信息tlv_124 平台网络信息tlv_128 手机设备信息tlv_16e 手机品牌TLV544 是设备id&#xff0…

MySQL-复合查询

文章目录复合查询基础查询多表查询自连接子查询单行子查询多行子查询多列子查询合并查询uion会自动去重union all就是不去重union all就是不去重复合查询 基础查询 查询工资高于500或者岗位为MANAGER的员工&#xff0c;同时名字首字母是J select * from emp where (sal>500…

ADI Blackfin DSP处理器-BF533的开发详解54:CVBS输出(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 CVBS OUT 视频输出 硬件实现原理 CVBS_OUT 子卡板连接在 ADSP-EDU-BF53x 开发板的扩展端口 PORT3 和 PORT4 上&#xff0c;板卡插入时&#xff0…

pytest + yaml 框架 -14.钉钉机器人通知测试结果

前言 当用例执行完成后&#xff0c;希望能给报告反馈&#xff0c;常见的报告反馈有&#xff1a;邮箱/钉钉群/飞书/企业微信 等。 pip 安装插件 pip install pytest-yaml-yoyo钉钉机器人通知测试结果功能在v1.1.1版本实现 钉钉机器人设置 钉钉机器人的设置请参考官方API文档…

实验2 VLAN的划分及VLAN间通信的配置

实验2 VLAN的划分及VLAN间通信的配置一、实验目的二、实验要求三、实验步骤&#xff0c;数据记录及处理四、实验总结一、实验目的 掌握VLAN的划分及VLAN间通信的配置方法 二、实验要求 交换机在没有划分虚拟网络时&#xff0c;都默认属于VLAN1&#xff0c;可以相互通信。通过…

【链表面试题】——剑指 Offer : 复杂链表(带随机指针)的复制

文章目录前言1.题目介绍2. 题目分析3. 思路讲解思路1思路2步骤1步骤2步骤34. 分析图及源码展示前言 这篇文章&#xff0c;我们一起来解决一道与链表相关的经典面试题&#xff1a;复杂链表&#xff08;带随机指针&#xff09;的复制。 1.题目介绍 我们先来一起了解一下这道题&…