【Linux从入门到精通】进程的控制(进程替换)

  本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助 

文章目录

一、进程替换概念

二、进程替换函数

2、1 execl

2、2 execlp

2、3 execv

2、3 execle

2、4 execve

三、总结


🙋‍♂️ 作者:@Ggggggtm 🙋‍♂️

👀 专栏:Linux从入门到精通  👀

💥 标题:进程控制💥

 ❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️ 

一、进程替换概念

  我们知道,fork() 创建子进程,子进程的代码和数据是和父进程共享一份的。当对任意一个进程修改时,就会发生写时拷贝。当时我们就想让子进程执行一份全新的代码呢?那我们可以使用进程替换。

  程序替换就是使用一个接口来实现的。把磁盘上的可执行程序加载到进程的地址空间上。可结合下图理解:

  进程替换就是把磁盘上的可执行程序加载到了内存中已经在运行的进程中,加载上的新程序会与原来的进程的页表构成新的映射关系,实际上并没有创建新的进程

二、进程替换函数

2、1 execl

  我们先来看一下execl()函数怎么使用,如下图:

  第一个参数是指你所要替换程序的路径。后面的参数是要怎么执行该程序,是一个可变参数列表,但是最后一个参数必须为空。具体使用如下:

#include<stdio.h>    
#include<unistd.h>    
#include<stdlib.h>    
    
int main()    
{    
    printf("hello linux\n");    
    
    execl("/usr/bin/ls","ls","-l",NULL);                                                                                                                     
    
    printf("hello linux\n");    
    
    exit(111);    
    return 0;    
}  

  我们看如下运行结果:

  确实执行了ls -l 的命令,但是并没有往下接着执行打印和退出!!!怎么没有打印呢?execl是程序替换,调用该函数后,会将当前的进程所有代码和数据进行替换。所以一旦调用成功,后续的代码将不会在被执行。

  exec()系列函数在成功时不会返回,只有在发生错误时才会返回-1。这是因为当exec()函数成功地加载新的可执行程序后,它会在当前进程上下文中完全替换掉当前进程的映像,包括代码、数据、堆栈等。这使得原先的进程状态被新的可执行程序取代,所以在成功加载新程序后,旧程序不再存在,也就无法进行返回操作了。

2、2 execlp

  execlp函数对比execl函数,就是所要替换的程序可以自己不带路径。execlp中的 p 指的意思是环境变量PATH,可以默认去找所要替换的程序路径。代码如下:

  #include<stdio.h>    
  #include<unistd.h>    
  #include<stdlib.h>    
      
  int main()    
  {    
      printf("hello linux\n");    
      
      //execl("/usr/bin/ls","ls","-l",NULL);    
      execlp("ls","ls","-l","-a",NULL);                                                                                                                      
                                                                     
      printf("hello linux\n");        
                                      
      exit(111);                      
      return 0;                       
  } 

  运行结果如下:

2、3 execv

  我们再来看一下execv函数的使用。如下图:

  其实对比execl函数不难发现,l 表示list的意思,也就是参数列表一个一个列出来。execv函数中的 v 表示vector,参数列表是一个数组。我们可看如下代码:

  #include<stdio.h>    
  #include<unistd.h>    
  #include<stdlib.h>    
      
  char* const _argv[]={"ls","-l","-a",NULL};                                                                                                                 
      
  int main()    
  {    
      printf("hello linux\n");    
      
      //execl("/usr/bin/ls","ls","-l",NULL);    
      
      execv("/usr/bin/ls",_argv);    
      printf("hello linux\n");    
      
      exit(111);    
      return 0;    
  } 

   运行结果如下:

2、3 execle

  我们这里就不再解释execvp了,对比上述讲到很容易理解。直接看execle函数。我们先看execle函数怎么使用:

  其实我们也不难发现,对比execl函数,参数列表最后多出来一个指针数组。这个指针数组就是维护的环境变量。为了更好的演示该函数,我们先写一下一个我们自己生成的可执行程序去调用我们另一个自己生成的可执行程序。代码如下:

//“————————————————myexec.c————————————————————”
  #include<stdio.h>    
  #include<unistd.h>    
  #include<stdlib.h>    
      
  const char* myflie="/home/gtm/primer/test/test_7_23/mycmd";    
  int main(int argc,char* argv[],char* env[])                                                                                                                
  {    
      printf("hello linux\n");    
      
      //execl("/usr/bin/ls","ls","-l",NULL);    
      //execlp("ls","ls","-l","-a",NULL);    
      
      execle(myflie,"mycmd","-a",NULL,env);    
      //execv("/usr/bin/ls",_argv);    
      return 0;    
  }  

//“————————————————mycmd.c————————————————————”
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// ./mycmd -a/-b/-c...
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("can not execute!\n");
        exit(1);
    }

    //MY_105_VAL: 目前并不存在!
    printf("获取环境变量: hello: %s\n", getenv("hello"));
                                                                                  
    if(strcmp(argv[1], "-a") == 0)                                            
    {                                                                         
        printf("hello a!\n");                                                 
    }                                                                         
    else if(strcmp(argv[1], "-b") == 0)                                       
    {                                                                         
        printf("hello b!\n");                                                 
    }                                                                                                                                                        
    else{                                                                     
        printf("default!\n");                                                 
    }                                                                                      
                                                                              
    return 0;                                                                 
}

  上述代码是在不同的源文件,上述代码中有所标述。我们想要的就是用myexec去调用mycmd。我们在mycmd中想要获取环境变量 hello 的值,但是哦我们并没有设置。所以环境变量hello的值为null。我们看运行结果:

  但是我们要在myexec中设置了hello环境变量,

  #include<stdio.h>    
  #include<unistd.h>    
  #include<stdlib.h>    
      
  const char* myflie="/home/gtm/primer/test/test_7_23/mycmd";    
  int main(int argc,char* argv[],char* env[])    
  {    
      printf("hello linux\n");    
      
      //execl("/usr/bin/ls","ls","-l",NULL);    
      //execlp("ls","ls","-l","-a",NULL);    
      
      const char* _env[]={"hello=20230724",NULL};    
      execle(myflie,"mycmd","-a",NULL,_env);                                                                                                                 
      //execv("/usr/bin/ls",_argv);    
      return 0;    
  }    

  我们再来看运行结果:

  当然,环境变量hello就可以获取相应的值。 

2、4 execve

  execve函数是属于系统调用函数。我们上述讲到的,如下图:

 

  都是语言级别的函数,底层封装的都是execve函数。事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve。为什么还要封装呢?直接使用execve多好啊。原因是封装后,我们也可以很直接的感受到,应用的场景变多了。其次是用起来,见名知其意。

三、总结

   在C++中,exec()系列函数提供了一种在程序中执行外部命令或可执行文件的方法。这些函数包括:execvp()、execv()、execvpe()、execlp()、execl()、execle()和execve()。

  1. execvp()函数:

    • 原型:int execvp(const char *file, char *const argv[]);
    • 功能:用于在指定的文件路径中搜索可执行文件,并用指定的参数列表运行该文件。
    • 优点:可以直接使用文件名作为参数,而无需提供文件路径。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  2. execv()函数:

    • 原型:int execv(const char *path, char *const argv[]);
    • 功能:在指定的文件路径中搜索可执行文件并用指定的参数列表运行该文件。
    • 优点:需要提供文件路径,因此可以明确指定要执行的文件的位置。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  3. execvpe()函数:

    • 原型:int execvpe(const char *file, char *const argv[], char *const envp[]);
    • 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
    • 优点:除了搜索文件路径外,还可以指定环境变量。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  4. execlp()函数:

    • 原型:int execlp(const char *file, const char *arg, ...);
    • 功能:在系统的环境变量所指定的路径中搜索可执行文件并用指定的参数列表运行该文件。
    • 优点:可以直接使用文件名和参数作为参数,而无需提供文件路径。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  5. execl()函数:

    • 原型:int execl(const char *path, const char *arg, ...);
    • 功能:在指定的文件路径中搜索可执行文件并用指定的参数列表运行该文件。
    • 优点:需要提供文件路径和参数,因此可以明确指定要执行的文件的位置和所需的参数。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  6. execle()函数:

    • 原型:int execle(const char *path, const char *arg, ..., char *const envp[]);
    • 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
    • 优点:除了搜索文件路径外,还可以指定环境变量。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。
  7. execve()函数:

    • 原型:int execve(const char *filename, char *const argv[], char *const envp[]);
    • 功能:在指定的文件路径和环境变量中搜索可执行文件,并用指定的参数列表运行该文件。
    • 优点:需要提供文件路径和参数,以及环境变量,因此可以明确指定要执行的文件的位置、所需的参数和运行环境。
    • 返回值:如果函数执行成功,则不会返回任何值;如果函数执行失败,则会返回-1。

  exec()系列函数允许程序在运行时调用其他可执行文件,以实现更复杂的功能。这些函数提供了不同的方式来指定可执行文件的路径、传递参数和设置环境变量,根据具体的需求,可以选择合适的函数来使用。请注意,exec()函数族在执行成功后,会将当前进程替换为新的进程,因此之后的代码不会被执行到。

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

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

相关文章

视频讲解Codeforces Round 887 (Div. 2)(A--C)

文章目录 A. Desorting1、板书2、代码 B. Fibonaccharsis1、板书2、代码 C. Ntarsis Set1、板书2、代码 视频讲解Codeforces Round 887 (Div. 2)&#xff08;A–C&#xff09; A. Desorting 1、板书 2、代码 #include<bits/stdc.h> #define endl \n #define INF 0x3f…

区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型

区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型 目录 区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRF随机森林分位数回归时间序列区间预测模型&#xff1…

从零到一nvm、npm、cnpm、yarn、vue全套安装和环境配置以及创建新项目和如何运行人家的项目大全,最详细,保姆级

NVM 1.下载 下载地址&#xff1a;Releases coreybutler/nvm-windows GitHub 可能需要开启魔法 划到下面。找到如图所示的文件下载即可2. 2.安装&#xff08;要记住安装的路径&#xff09; 基本一键默认即可&#xff0c;你要修改路径也可以&#xff0c;但不建议 下载好…

【开发问题】flink-cdc不用数据库之间的,不同类型的转化

不同的数据库之期间数据类型转化 问题来源与原因解决过程&#xff0c;思路错误&#xff0c;导致各种错误错误思路是什么 正确解决方式&#xff0c;找官网对应的链接器&#xff0c;数据转化 问题来源与原因 我一开始是flink-cdc&#xff0c;oracle2Mysql&#xff0c;sql 我一开…

删除Windows顽固启动项Program

卸载软件之后可能会遇到任务管理器中启动项显示有Program这种无效项目的情况 无效项目如图所示: 解决方法 打开注册表 Win R 打开注册表后定位到 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run 可以直接复制粘贴到地址栏进行跳…

Orangepi docker Home Assistant部署

手册上多数应用在树莓派用过&#xff0c;发现一个Home Assistant之前没搞过 按照手册先安装docker&#xff0c;使用enable_docker.sh 然后使用 docker run hello-world 来测试docker是否成功&#xff0c;如果hello from docker&#xff0c;即正常 通过以下docker命令搜索hom…

微服务探索之路06篇k8s配置文件Yaml部署Redis使用Helm部署MongoDB和kafka

1 安装Redis 1.1创建配置文件redis.conf 切换到自己的目录下如本文是放在/home/ubuntu下 cd /home/ubuntuvim redis.conf bind 0.0.0.0 protected-mode yes port 6379 requirepass qwe123456 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no pidfile /var/run/r…

【Spring】ApplicationEventPublisher 发布订阅模式

概念 关于发布订阅这个词&#xff0c;其实不仅仅出现在Spring框架当中&#xff0c;其实在Redis中也有存在&#xff08;其对应的是convertAndSend()方法&#xff09;&#xff0c;还有在MQ消息队列里也是有的&#xff0c;但这里就主要介绍的是关于Spring框架的ApplicationEventPu…

怎么把PDF转为word?1分钟解决难题

PDF文件在我们的电脑上应用非常广泛&#xff0c;由于其较高的安全性和兼容性&#xff0c;得到了广泛的认可。然而&#xff0c;对于一些人来说&#xff0c;PDF文件不能直接进行编辑和修改可能是一个问题。因此&#xff0c;通常我们需要将其转换为Word格式&#xff0c;以便在Word…

成为“AI+的UGC社交平台”,亚马逊云科技助力博宇盖乐向“3D UGC社交门户”迈进

随着元宇宙浪潮逐渐升温&#xff0c;以玩家为主导的UGC游戏平台获得空前关注。多元化的视觉呈现方式&#xff0c;人人可参与、交互的玩法生态&#xff0c;具有UGC属性的游戏平台在极大提升玩家参与度、增加游戏趣味性的同时&#xff0c;也为游戏行业的内容创作带来了新的想象空…

5分钟开发一个AI论文抓取和ChatGPT提炼应用

5分钟开发一个AI论文抓取和ChatGPT提炼应用 第一步 点击“即刻开始” -选择模板 python -修改标题 “AIPaper”&#xff0c;项目标识“AIPaper”&#xff0c;点击“创建项目” 第二步 在编程区域右侧AI区域&#xff0c;输入框输入以下内容&#xff1a; 请根据下面的内容&…

MacBook外接键盘修改键位

众所周知&#xff0c;MacBook的键盘和Windows差别很大&#xff0c;比如我们最常用的ctrlcv在Mac下是commandcv…而外接键盘往往是Windows布局&#xff0c;因此如何修改外接键盘键位就是一件很重要的事情&#xff01; 首先&#xff0c;我们要知道Win键在Mac系统中是多余的&…

客户案例 | 思腾合力服务器助力西安电子科技大学人工智能实验室建设

客户介绍 西安电子科技大学是以信息与电子学科为主&#xff0c;工、理、管、文多学科协调发展的全国重点大学&#xff0c;直属教育部&#xff0c;是国家“优势学科创新平台”项目和“211工程”项目重点建设高校之一、国家双创示范基地之一、首批35所示范性软件学院、首批9所示范…

机器学习术语解析与应用(一)

文章目录 &#x1f340;引言&#x1f340;数据集&#x1f340;特征工程&#xff08;Feature Engineering&#xff09;&#x1f340;模型&#xff08;Model&#xff09;&#x1f340;算法&#xff08;Algorithm&#xff09;&#x1f340;训练&#xff08;Training&#xff09;&a…

电脑风扇声音大怎么办?最全解决方法分享!

家人们谁懂啊&#xff01;电脑风扇声音太大了&#xff0c;每天用电脑的时候都感觉特别特别的吵&#xff0c;真的非常窒息&#xff0c;有什么方法可以改善电脑风扇声太吵的情况吗&#xff1f; 电脑风扇是保持电脑内部温度稳定的重要组件&#xff0c;其正常运行有利于保障我们电脑…

学好Elasticsearch系列-核心概念

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 文章目录 节点角色master&#xff1a;候选节点data&#xff1a;数据节点Ingest&#xff1a;预处理节点ml&#xff1a;机器学习节点remote_ cluster_ client&#xff1a;候选客户端节点transform&#xff1a;…

Flutter实现点击头像更新头像的功能,本地相册选取和调用相机两种方式的实现

文章目录 需求实现的效果如图代码实现代码分析用InkWell包住了我们的头像&#xff0c;这样来监听点击头像的事件用showDialog弹出提示框让用户选择是从相册里选择头像还是使用相机来拍照用image_picker实现从设备的相册或相机中选择图片或拍照 需求 Flutter实现点击头像更新头…

vite打包性能优化以及填坑

目录 前言 项目优化前 分析 优化 拆分包 去除debugger CDN 加速 按需导入 文件压缩 图片压缩 viteImagemin报错 填坑 坑1 坑2 总结 配置 前言 最近在使用 Vite4.0 构建一个中型前端项目的过程中&#xff0c;遇到了一些坑&#xff0c;也做了一些项目在构建生产环…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能&#xff1a;2.2 目录界面&#xff1a;2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…

Java 贪心算法经典问题解决

文章目录 分金条题目思路代码实现测试用例以及结果输出 花费资金做项目最大收益题目思路代码实现测试用例以及结果输出 预定会议室题目思路代码实现测试用例以及结果输出 取中位数题目思路代码实现测试用例以及结果输出 最低字典序题目思路代码实现测试用例以及结果输出 结语 分…