【Linux】进程理解与学习-程序替换

 环境:centos7.6,腾讯云服务器
Linux文章都放在了专栏:【Linux】欢迎支持订阅

相关文章推荐:

【Linux】冯.诺依曼体系结构与操作系统

【Linux】进程理解与学习Ⅰ-进程概念

【Linux】进程理解与学习Ⅱ-进程状态

【Linux】进程理解与学习Ⅲ-环境变量

【Linux】进程理解与学习Ⅳ-进程地址空间

【Linux】进程控制(创建、终止、等待)

------------------------------------------------------------------------------------------------------

浅谈Linux下的shell--BASH

【Linux】进程优先级&前后台理解


前言

在前文,我们学习了fork函数创建子进程,而创建子进程主要就是为了让它帮我们执行特定的任务。而我们之前所学的都只是为了让子进程帮我们执行父进程的部分代码(通过执行流分流的方式),并没有执行一个全新的程序。但实际上子进程也是可以执行一个新的程序。子进程可以通过程序替换的方式将父进程的代码与数据替换成新的程序对应的代码与数据。本文将对此进行探讨。

程序替换

进程可以通过程序替换的方式来执行一个全新的程序,具体的做法则是通过对应的程序替换的几个系统调用函数来实现,下面先来看一下程序替换的现象,根据这个现象来分析程序替换实现的原理。

程序替换的现象

接下来我们通过该现象对此进行分析,现象如下:

 我们可以看到,我们最终的执行结果并不是像我们想象的那样,而是将本该打印的end给替换成了执行ls这个指令。那么具体的原理是怎样的呢?如下图所示:

程序替换的原理

原理图解

通过上图,也解释了为什么在执行我们的进程时,execl函数后面的end的打印并没有执行,因为在我们执行完打印begin后,开始调用系统调用函数execl,将新的程序(ls)的代码与数据加载到内存对应的位置,将老进程的代码与数据给替换掉,所以就执行不了后面的打印end指令了。(这里注意的是,程序替换是实现的代码与数据的整体替换

 那么这里不仅有一个问题:在进程替换时,有没有产生新的进程呢?

答案是没有的,因为我们仅仅只是将老进程里面的代码与数据,替换成新程序的代码与数据,实现程序替换。并没有产生新的进程。正如上图所示,原进程对应的pcb并没有发生改变,也没有产生新的pcb。

当然我们也可以通过代码来验证一下:

多进程对应的程序替换

当然,假如我们使用fork创建子进程,让子进程完成程序替换,子进程的程序替换并不会影响父进程,这是因为父子进程都有各自独立的PCB,并且由于写时拷贝机制的存在,使得父子进程互相独立,互不影响。

程序替换函数

接下来我们讲一下几个程序替换函数。总体一共有7个,其中这七个里的六个实际上底层都是调用第七个。总体如下:

exec函数家族关系

 

对于这些exec函数,它们都只具有失败时候的返回值,当程序替换失败时,会返回-1,同时继续往后执行exec后面的指令,当替换成功时会直接执行替换后的新程序。接下来逐一介绍。

execl函数

首先介绍的是execl函数,我们在上面的演示中用到的就是该函数。

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

对于该函数来说:

  • 返回值失败返回-1,替换成功执行新程序。
  • path参数新程序的路径位置(找到它)
  • arg参数:新程序名称(执行它)
  • ...:可变参数,这里表示命令行参数选项(就比如上文所示-a -l),以NULL结尾。

举例:

 execv

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

该函数我们发现,之前的l变成了v,实际上其实就是用了一个函数指针数组,将之前的"ls","-a","-l"的地址放进数组里,数组最后一位元素为NULL,然后将该指针数组的起始地址(数组名),当作execv的第二个参数。

对于该函数来说:

  • 返回值:替换失败返回-1
  • path参数程序所在路径
  • argv[]指针数组的地址(数组名)

举例:

 execlp

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

对于该函数,我们发现之前的path参数更换成了file,然后函数名中加了个p,其实代表的意思就是,会在PATH环境变量中根据file名查找file的路径,后面的参数代表的与execl一样。

对于该函数:

  • 返回值:替换失败返回-1
  • file传程序名,会根据程序名自动在PATH中搜索该程序对应的路径。(找到它,不需要我们传具体的路径,会自动匹配)
  • 后面的arg表示程序名(执行它)
  • ...:可变参数,表示新程序的命令行参数选项(怎么执行,比如:-a -l),以NULL结尾

举例:

 不过这里需要注意的是,自动搜索匹配路径是指在PATH环境变量中搜寻,假如一个新程序的路径并不在PATH中,则会匹配不上,就导致替换失败。如下:

程序替换失败

 execvp

我们发现,该函数变成了vp结尾,v表示数组(指针数组)的形式,p表示自动搜索匹配环境变量PATH中的路径。

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

对于该函数:

  • 返回值:替换失败返回-1
  • file程序名,会根据程序名自动搜索在PATH中对应的路径
  • argv[]指针数组,用法同execv

举例:

 同样,这里自动匹配路径指的是在PATH中搜索,假如我们想要执行替换自己写的程序,就要将我们写的程序的路径用export导入环境变量即可。

execle

这里的e,表示environ,即表示环境变量表。也就是说,我们可以将当前程序的替换成新程序,同时将老的环境变量表也传给新程序。

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

对于该函数:

  • 返回值:替换失败返回-1
  • 用法同execl,只是最后加了一个参数,用来传给新程序环境变量表(这个环境变量表可以是自己定义,也可以是系统的)。
  • 当然如果将自定义的环境变量表传给新程序的话,新程序的原有的系统环境变量表就会被覆盖掉。

举例:

execvpe

我们发现,这里v(数组)、p(PATH)、e(环境变量表),三者都集齐了。  

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

 对于该函数:

  • 返回值:替换失败返回-1
  • file:会自动根据file匹配PATH中的路径,不需要我们手动写全
  • argv[]:指针数组
  • envp[]:环境变量表(可以是系统的,也可以是自定义的)

举例:

newtest程序:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
 int main()
 {
   extern char** environ;
   printf("我是新程序,我的环境变量表中的前三个环境变量是:\n");                                                                               
   for(int i=0;i<3; ++i)
   {
     printf("%d:%s\n",i,environ[i]);
   }
   return 0;
 }

运行newtest:

 mytest程序:实现程序替换(在此之前已经将newtest的路径导入了PATH

 #include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/wait.h>
 #include<fcntl.h>
  
 int main()
 {
   pid_t id=fork();//创建子进程
   if(id == 0)
   {
     //child
    printf("我是子进程,pid:%d\n",getpid());
    char*const envp[]={"myval=520",NULL};//自定义环境变量表
    const char* argv[]={"newtest",NULL};//指针数组
    execvpe("newtest",argv,envp);//注意:我已经将newtest的路径导进了PATH
    printf("程序替换失败\n");                                                                                                               
    exit(1);
  }
   //father
   int status=0;
   waitpid(id,&status,0);//进程等待
   if(WEXITSTATUS(status)!=1)
   {
     printf("进程替换成功\n");
   }
   return 0;
 }
已经将新程序路径导入环境变量

 

execve

execve为最正宗的系统调用函数,我们这里讲解的其它的系统调用其实底层都是调用了该函数。

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

对于该函数:

  • 替换失败返回-1
  • 参数filename表示新程序的路径(找到它)
  • argv[]:指针数组,存放新程序名(执行它),以及程序对应的命令行参数列表(比如ls的-a -l),最后以NULL结束。
  • envp[]环境变量表(可自定义)传入环境变量表后,新程序的老的环境变量表就被这里的envp环境变量表给覆盖了。

举例:

额外补充

对于以上的这么多系统调用函数,可能看了都头大,但是仔细看,其实会有很多共性,可以利用这 个特点来更加巧妙地记住这些函数的用法。

联想记忆exec函数家族:

  • 带有l的:l联想list,所以参数中要带有NULL,就好像一个链表一样。("ls", "-l"," -a"," NULL)
  • 带有v的:v联想vector,说明第二个参数传的是个数组(指针数组)
  • 带有p的:p联想PATH,说明第一个参数不需要我们传具体的路径,只需要传个程序名即可(会自动搜索PATH路径进行匹配)。
  • 带有e的:说明最后一个参数是用来传环境变量表(也可以是自定义的环境变量表)的

end.

生活原本沉闷,但跑起来就会有风!🌹 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

想拿到10k-40k的offer,这些技能必不可少!作为程序员的你了解吗

总结了一份Java架构师的技能树&#xff0c;希望对Java编程的同学有点帮助 Java编程的技术点&#xff1a; ​ 计算机基础 ​ Java高级特性 设计模式 ​ 数据库 分布式系统 ​ 注意&#xff1a;下文主要是我个人的总结方法经验&#xff08;面试学习和刷题笔记&#xff09; 01…

aws codedeploy 在ec2实例和autoscaling组上进行蓝绿部署

参考资料 https://docs.amazonaws.cn/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.htmlhttps://docs.amazonaws.cn/zh_cn/codedeploy/latest/userguide/applications.html为 EC2/本地蓝/绿部署创建部署组&#xff08;控制台&#xff09; 部署ec2比较…

面试角度看问题:消息队列详解(万字长文,绝对值得一看)

面试角度看问题&#xff1a;消息队列详解前言一、消息队列是什么&#xff1f;二、为什么要使用消息队列&#xff1f;1.解耦2.异步3.削峰三、消息队列有什么缺点&#xff1f;1.系统可用性降低2.系统复杂度提高3.一致性问题四、如何保证消息队列的高可用&#xff1f;1.RabbitMQ 的…

zookeeper

目录 1.软件架构的发展 2.了解zookeeper 2.1概述 2.2zookeeper的应用场景 2.3安装zookeeper 2.4zookeeper客户端命令 3.zookeeper简单操作 3.1zookeeper的数据结构 3.2节点的分类 3.3java代码操作zookeeper节点 3.4zookeeper的watch机制 3.4.1介绍 3.4.2NodeCache…

ERD Online 4.0.11 在线数据库建模、元数据协作平台(免费、私有部署)

ERD Online 是全球第一个开源、免费在线数据建模、元数据管理平台。提供简单易用的元数据设计、关系图设计、SQL查询等功能&#xff0c;辅以版本、导入、导出、数据源、SQL解析、审计、团队协作等功能、方便我们快速、安全的管理数据库中的元数据。 4.0.11 ❝ :memo: fix(erd):…

5亿融资与重磅新品双发布,杉数以智能决策技术变革中国产业运营模式

2023年3月30日&#xff0c;由杉数科技举办的“智能决策重塑增长”2023杉数科技智能决策前沿峰会在北京举行。会上发布了杉数新一轮融资消息&#xff0c;同时&#xff0c;面向零售快消的决策优化产品计划宇宙&#xff08;Planiverse&#xff09;与面向工业制造的决策优化产品数弈…

Flink (四) --------- Flink 运行时架构

目录一、系统架构1. 整体构成2. 作业管理器&#xff08;JobManager&#xff09;3. 任务管理器&#xff08;TaskManager&#xff09;二、作业提交流程1. 高层级抽象视角2. 独立模式&#xff08;Standalone&#xff09;3. YARN 集群三、 一些重要概念1. 数据流图&#xff08;Data…

C的实用笔记36——几种常用的字符串处理API(一)

0、const关键字 1、知识点&#xff1a;const是与存储相关的关键字&#xff0c;用作常量声明&#xff0c;修饰普通变量和指针变量&#xff0c;表示只读。const修饰普通变量&#xff1a;&#xff0c;修饰后变量从可修改的左值变成不可修改的左值 const修饰指针变量&#xff1a;分…

redis源码解析(四)——ziplist

版本&#xff1a;redis - 5.0.4 参考资料&#xff1a;redis设计与实现 文件&#xff1a;src下的ziplist.c ziplist.h 一、基础知识1、压缩列表的各个组成部分及详细说明2、列表节点3、encoding二、连锁更新三、ziplist.hquickList一、基础知识 压缩列表是Redis为了节约内存而开…

陌生人社交软件如何破冰?

据艾媒咨询的数据显示&#xff0c;2020年中国移动社交用户规模已达9.24亿人&#xff0c;预计2022年中国移动社交用户整体突破10亿人。而早在2020年&#xff0c;我国陌生人社交用户规模已经达到了6.49亿人&#xff0c;虽然增速有所放缓&#xff0c;但整体规模还是较为庞大。 艾媒…

操作系统笔记——进程管理

操作系统笔记——进程管理2. 进程管理2.1 进程与线程2.1.1 进程的引入前趋图程序的顺序执行程序的并发执行2.1.2 进程的定义及描述进程的定义进程的特征进程和程序的关系进程与作业的区别进程的组成2.1.3 进程的状态与转换进程的5种基本状态进程的状态的相互转换2.1.4 进程的控…

java常见锁策略分享(包括cas和synchronized的优化)

前言 锁策略学习思维导图: 1.常见锁策略 ① 乐观锁和悲观锁 ● 它们是根据锁冲突的预测,如果预测锁冲突比较小,那就是乐观锁,反之,就是悲观锁. ● 举个例子:高考前夕,我总觉得高考题会很难,然后拼命做各种科目的题,全副武装的去应对高考,而我妈则觉得高考只是人生的一个阶段而…

PCB模块化设计04——USB-Type-C PCB布局布线设计规范

目录PCB模块化设计04——USB-Type-C PCB布局布线设计规范USB Type-C功能介绍信号图示Type-C接口引脚定义USB 2.0差分对电源和接地引脚RX和TX引脚CC1和CC2针脚VCONN引脚SBU1和SBU2针脚USB供电PCB设计布线要求PCB模块化设计04——USB-Type-C PCB布局布线设计规范 USB Type-C US…

STC的官网,是我永远忘不掉的炼丹炉

搞电子的&#xff0c;应该都搞过8051搞8051的&#xff0c;那应该都搞过STC在国内&#xff0c;STC已经成为了8051的代名词http://www.stcmcudata.com/如果你刚开始搞嵌入式&#xff0c;应该学单片机&#xff0c;你学习单片机&#xff0c;就应该学习下8051&#xff0c;学习8051&a…

Python+Pygame实现简单的单词小游戏

语言是一种艺术&#xff0c;但是作为语言的基础——词汇&#xff0c;却不像艺术那样赏心悦目。不断的记忆与复习&#xff0c;让词汇成为很多孩子在学习英语时&#xff0c;最难完全攻克的关卡。本文就来用Python制作一个简单的英语单词游戏吧 前言 语言是一种艺术&#xff0c;但…

【ArcGIS Pro二次开发】(17):打开GDB、SHP、CAD等各种数据

一、打开GDB数据库 // 输入一个数据库路径string gdbPath "C:\Users\Administrator\Documents\ArcGIS\Projects\Test\Test.gdb";await QueuedTask.Run(() >{// 如果文件夹存在并且包含有效的地理数据库&#xff0c;则会打开地理数据库。using (Geodatabase geoda…

【单片机/普中A2】学习笔记1-配置环境与STC-ISP烧录

目录前言连接到开发板micro-usb 测试安装串口驱动烧写准备源码烧录前言 目前我们的开发需求很简单&#xff0c;仅需三个软件&#xff1a; keli5 编写代码proteus8 professional 描绘电路板STC-ISP 串口烧录 具体教程在 CSDN 等博客平台上已经有很多&#xff0c;这里就不再赘述…

(排序2)希尔排序

写希尔排序注意&#xff1a; 写新元素融入有序数组的过程(end&tmp)将这个过程给多次类比到需要排序的一串数据中 (for&while)排完一组不够&#xff0c;需要排gap组 (再来for)敲定gap下标关系&#xff1a; 希尔排序与直接插入排序的区别与联系 希尔排序的话也叫做缩小…

刷题笔记【3】| 快速刷完67道剑指offer(Java版)

本文已收录于专栏&#x1f33b;《刷题笔记》文章目录前言&#x1f3a8; 1、斐波那契数列题目描述思路一&#xff08;递归&#xff09;思路二&#xff08;循环&#xff09;&#x1f3a8; 2、跳台阶题目描述思路一&#xff08;递归&#xff09;思路二&#xff08;循环&#xff09…

03-03 周五 镜像安装sshd和jupyter以及修改密码

03-03 周五 镜像安装sshd和jupyter以及修改密码时间版本修改人描述2023年3月3日15:34:49V0.1宋全恒新建文档 简介 由于在镜像中需要进行jupyter和sshd的安装&#xff0c;并且需要进行密码的修改&#xff0c;因此在该文档中记录了这两个交互方式的工程设计。 在线加密 在线加密…
最新文章