Linux操作系统~进程替换,exec系列函数的使用

news2025/7/18 8:19:22

目录

1.概念/原理

(1).替换原理

(2).子进程调用execl执行程序替换,为什么父进程不受影响?

(3).exec*返回值

2.替换函数exec

execl

execv

execlp

execvp的(execv)

execve的参数(execle)

技:Makefile一次生成多个可执行文件

Q:为什么这里的clean要设置为伪目标?

exec系列函数总结


上一篇文章我们创建子进程的目的:  if else 让子进程执行父进程代码的一部分

如果我想让子进程执行一个“全新的程序”呢?? ————这就需要用到进程替换

1.概念/原理

        进程替换就是指进程不变(进程的pcb,进程地址空间不变),仅仅用替换当前进程的代码和数据的技术(新程序的替换旧进程的),叫做进程的程序替换,这样就好像子进程执行了一个全新的程序。

--有没有创建新的进程呢?   答案是没有

(1).替换原理

        用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

程序替换的本质是不是就是把程序的进程代码+数据(加载进特定进程的上下文中!!

C/C++程序要运行,必须的先加载到内存中!

如何加载呢?使用加载器

加载器的底层原理就是使用exec*程序替换函数


(2).子进程调用execl执行程序替换,为什么父进程不受影响?

父子代码难道不是共享的吗?为什么新程序替换了子进程的代码和数据以后,父进程不受影响呢?

        因为进程是具有独立性的,进程程序替换会更改代码区的代码,此时也会发生写时拷贝,拷贝一份代码和数据给子进程,然后再将新程序中的代码和数据替换子进程中的。


(3).exec*返回值

        只要进程的程序替换成功,就不会执行后续代码,意味着exec*函数,成功的时候,不需要返回值检测(exec系列函数执行成功以后,原进程中的代码和数据都会被替换掉,自然也就不会执行exec*后面的代码,exec*自然也就不会返回了;如果exec*返回了,那exec系列函数一定是执行失败了。

只要exec*返回了,就一定是因为调用失败了!


2.替换函数exec

其实有六种以exec开头的函数,统称exec函数:

#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[]);

int execv(const char *path, char *const argv[]);

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

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

函数解释:

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

命名理解

  1. l(list) : 表示参数采用列表(比如execl)
  2. v(vector) : 参数用数组
  3. p(path) : 有p自动搜索环境变量PATH
  4. e(env) : 表示自己维护环境变量(自己定义环境变量替代系统的环境变量)

execl

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

  • l(list) : 表示参数采用列表(比如execl)

  • 第一个参数是path,填的就是你要执行的目标程序的全路径,即所在路径/文件名
  • 第二个参数之后,表示的是可变参数列表,要执行目标程序在命令行上具体该怎么执行,这里参数就需要一个个传递过去(“ls” “-a”  “-l”三个参数,缺一不可),最后必须传入NULL,作为参数传递的结束。
execl("/usr/bin/ls", "ls", "-l");

execv

int execv(const char *path, char *const argv[]);

  • v(vector) : 参数用数组

第一个参数和execl一样,path

第二个参数是一个指针数组,将execl中按照列表形式给出的参数放到这个数组里面。(最后需要加上NULL)

可以理解为它把这个参数数组,直接喂给了ls命令的main函数中的命令行参数数组argv

char* args[] = {"/usr/bin/ls","-al",NULL};
execvp("ls",args);

execlp

int execlp(const char *file, const char *arg, ...);

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

  • p(path) : 有p自动搜索环境变量PATH

带了l所以是参数是以列表的形式给出

带了p所以第一个参数只需要给出文件名即可,在调用execlp的时候会帮我们根据环境变量PATH帮助我们找这个文件。

        要注意这两个ls的区别,第一个是指定程序/文件名,第二个ls是要在命令行上给出的参数(想要执行ls命令,ls本身也要给出)

execlp("ls", "ls", "-l");

execvp的(execv)

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

  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH

第一个参数只需要给文件名

第二个参数给参数数组

char* args[] = {"ls","-al",NULL};
execvp("ls",args);

execve的参数(execle)

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

  • e(env) : 表示自己维护环境变量(自己定义环境变量替代系统的环境变量)

第一个参数给全路径

第二个参数给参数数组

第三个参数表示自己定义一个环境变量,然后传进来,替换系统的环境变量

自己有两个C程序,调用一个(test7)的时候运行另一个程序(to_exe)

test7:

#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;

int main()
{
    pid_t fork_id = fork();
    if(fork_id > 0)
    //父进程
    {
        cout << "this is father" << endl;
        wait(nullptr);
    }
    else
    //子进程
    {
        cout << "this is child" << endl;
        char* args[] = {"ls","-al",NULL};
        char* envp[] = {"666第一个参数","666第二个参数","666第三个参数",nullptr};
        execve("./to_exe",args,envp);
    }
    // bool a = nullptr;  //虽然报错但是对
    return 0;
}

to_exe:

        这样我们就可以在调用的另一个程序(to_exe)中使用自己定义的环境变量,打印出来,而不是系统的环境变量了。(如果直接运行to_exe,打印出来的是系统的环境变量)

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main()
{
    cout << "to_exe is running" << endl;
    extern char **environ;  //获取当前的环境变量(一个字符串数组)
    for (int i = 0; environ[i]; i++)
    {
        printf("%s\n", environ[i]);
    }

    printf("my exe running .... done\n");
    return 0;
}

 运行结果:

 


技:Makefile一次生成多个可执行文件

        Makefile默认只会生成第一个文件,所以我们可以声明一个目标all,然后将我们要生成的可执行文件作为all的依赖关系即可。

Q:为什么这里的clean要设置为伪目标?

        如果当前目录下存在文件名为clean的文件时,我们在shell中执行命令make clean时,由于这个规则没有依赖文件,所以目标被认为是最新的,从而不去执行规则所定义的命令,因此命令rm将不会被执行。为了解决这个问题,删除clean文件或者是在Makefile中将目标 clean 声明为伪目标。

[zebra@VM-8-12-centos test7]$ make clean
make: `clean' is up to date.

exec系列函数总结

        这六个函数(加上execvpe一共七个)实际上只是参数上的不同,最终都是调用execve,系统给我们提供的实际上只有这一个接口,其他接口都是在此基础上封装出来的。(通过man手册也可以发现execve在man手册的2区内,表示是系统调用)

all:test7 to_exe
test7:test7.cc
	g++ -o $@ $^ -std=c++11
to_exe:to_exe.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -f test7

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

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

相关文章

Android Studio App开发之网络通信中使用POST方式调用HTTP接口实现应用更新功能(附源码 超详细必看)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、POST方式调用HTTP接口 POST方式把接口地址与请求报文分开&#xff0c;允许使用自定义的报文格式&#xff0c;由此扩大了该方式的应用场景。POST请求与GET请求主要有三处编码差异 1&#xff1a;在调用setRequestMethod方…

Kafka 消息队列 ( 一 ) 基本概念

0.MQ(message queue) 消息中间件 生活中的问题 : 快递员 给 你 送东西, 你必须 在家等着, (效率低) 可以 把东西 放 指定 的 地方(菜鸟驿站) , 你自己去取 , 指定 的地点(菜鸟驿站) 就是 MQ 消息队列中间件 0.1.开发中的问题 0.1.1.异步问题 0.1.2.业务解耦 0.1.3.流量削…

2. 信息在计算机中存储的格式

目录 一、信息存储&#xff1a; 1. 空间大小定义 2. 不同进制的转换方法 3. 各种数据类型所占字节数 4. 字节顺序 5. 字符串存储 6. 代码的二进制表示 7. 布尔代数运算 8. 逻辑运算 9. 移位运算 二、 整数表示 1. 有符号与无符号表示 1.1 表示范围 1.2 补码编码的…

C语言日记 35 拷贝构造函数

书P132&#xff1a; 拷贝构造函数的作用是 用已存在的对象初始化另一对象&#xff0c;两对象类类型应一样 在这里我们可以看到&#xff0c; 他对被拷贝的对象的要求只有“已存在的对象&#xff0c;两对象类类型一样”&#xff0c;也就是说他这里也没有说我们不能跨区域&…

使用 Spring Cloud Loadbalancer 实现客户端负载均衡

使用 Spring Cloud Loadbalancer 实现客户端负载均衡 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;使用 Spring Cloud Loadbalancer 实现客户端负载均衡 CSDN&#xff1a;使用 Spring Cloud Loadbalancer 实现客户端负载均衡 背景 在Spring Cloud G 版…

为什么 think-cell 图表中的标签显示为白色矩形?

有些标签的背景错误地变成白色&#xff0c;或显示幻灯片背景。当前版本的 PowerPoint 不会出现此问题。 •使用 PowerPoint 2007 打开 .ppt 文件并单击标签内部时&#xff0c;将显示正确的标签背景&#xff0c;但是在保存后重新打开该文件时&#xff0c;会返回不正确…

分布式系统的 38 个知识点

天天说分布式分布式&#xff0c;那么我们是否知道什么是分布式&#xff0c;分布式会遇到什么问题&#xff0c;有哪些理论支撑&#xff0c;有哪些经典的应对方案&#xff0c;业界是如何设计并保证分布式系统的高可用呢&#xff1f; 1. 架构设计 这一节将从一些经典的开源系统架…

5G无线技术基础自学系列 | 物理随机接入信道

素材来源&#xff1a;《5G无线网络优化实践》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 PRACH信道用于传输前导Preamble序列。gNB…

逆向-破零64位版本

// 排版有点乱&#xff0c;没有图片直观。 #include <stdio.h> #include <stdlib.h> #include <string.h> int f_14a2(int *va, int vb) { /*14a2: f3 0f 1e fa endbr64 14a6: 55 push %rbp 14a7:…

[附源码]java毕业设计基于Web的美食网站的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【背景渐变】 —— 就算没接触过也能 一遍学会哦

前期回顾 ​回顾 前期 把你喜欢css动画嵌入到浏览器中 —— css动画 项目_0.活在风浪里的博客-CSDN博客常用酷炫动画999合集&#xff0c;代码直接复制可用&#xff0c;总用你想找的&#xff0c;快来抱走吧&#xff0c;三连&#xff0c;停&#xff01;听鹅说&#xff0c;下…

2009年408大题总结

2009年408大题第41题第42题第43题第44题第45题第46题第47题第41题 这个最容易想到的方法就是举反例&#xff0c;但是我们可以分析一下&#xff0c;每一次都取最短的路径&#xff0c;实际上就是贪心策略的应用——每次都是最优&#xff0c;但是最终的结果却一般不是最优&#xf…

第十一节:抽象类和接口【java】

目录 &#x1f947;1. 抽象类 &#x1f4d8;1.1 抽象类概念 &#x1f4d2;1.2 抽象类语法 &#x1f4d7; 1.3 抽象类特性 &#x1f3f9;2. 接口 &#x1f4d9;2.1 接口的概念 &#x1f4d5;2.2 语法规则 &#x1f4d2;2.3 接口使用 &#x1f50e;2.3.1USB接口例子 &a…

【Google Colab】使用手册、教程;使用 Google Colab 免费使用 python 服务器

Colaboratory 是一个 Google 研究项目&#xff0c;旨在帮助传播机器学习培训和研究成果。它是一个 Jupyter 笔记本环境&#xff0c;不需要进行任何设置就可以使用&#xff0c;并且完全在云端运行。Colaboratory 笔记本存储在 Google 云端硬盘中&#xff0c;并且可以共享&#x…

超详细图解kafka生产消费流程

目录&#xff1a; 一条消息在kafka是如何生产的&#xff1f; 一条消息在kafka是如何存储的&#xff1f; 一条消息在kafka是如何消费的&#xff1f; Kafka为什么高性能&#xff1f; Kafka为什么高可用&#xff1f; 一&#xff0e;一条消息在kafka是如何存储的&#xff1f; …

【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由

文章目录目标代码0.动态地显示菜单&#xff1a;store1.动态注册路由2.解决刷新后摆平问题总代码本篇修改的代码文件tab.js参考视频&#xff1a; VUE项目&#xff0c;VUE项目实战&#xff0c;vue后台管理系统&#xff0c;前端面试&#xff0c;前端面试项目案例链接【前端】VueEl…

spring-IOC理论推导P3

1.新建一个项目。名字叫做spring-study 2.导包 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.23</version></dependency></dependencies&…

solr-7.7.3 搭建

solr-7.7.3 搭建 solr-7.7.3 搭建 文章目录solr-7.7.3 搭建一、前期准备安裝规划(一)资料下载(二)上传文件二、安裝(一)创建新用户(二)安装solr1.solr安装包解压到/opt/module2.将解压文件名修改为solr3.修改配置文件(三)分发文件&#xff08;四&#xff09;开启solr&#xff…

YOLOv5量化调优

目录 一、背景 二、模型调优 2.1 基准选取 2.1.1 官方精度数据 2.1.2 fp32bmodel的精度 2.1.3 int8bmodel精度数据 2.2 多图量化 2.3 预处理对齐&lmdb 2.4 网络图优化 2.4.1 per_channel优化 2.4.2 accuracy_opt优化 2.4.3 conv_group优化 2.4.4 总结 2.5 混…

python中使用xlrd、xlwt操作excel表格详解

最近遇到一个情景&#xff0c;就是定期生成并发送服务器使用情况报表&#xff0c;按照不同维度统计&#xff0c;涉及python对excel的操作&#xff0c;上网搜罗了一番&#xff0c;大多大同小异&#xff0c;而且不太能满足需求&#xff0c;不过经过一番对源码的"研究"&…