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

news2024/10/6 0:33:20

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

文章目录

一、进程替换概念

二、进程替换函数

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()函数族在执行成功后,会将当前进程替换为新的进程,因此之后的代码不会被执行到。

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

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

相关文章

SpringBoot项目修改Tomcat版本号

SpringBoot项目修改Tomcat版本号 前言如果项目是以jar包形式打包部署如果项目是以war包形式打包部署示例 仰天大笑出门去&#xff0c;我辈岂是蓬蒿人 前言 Springboot项目,默认是使用内嵌Tomcat servlet容器形式打包部署。关于怎么修改默认的版本号&#xff0c;捣鼓了好久终于…

ChatGPT的工作原理:从输入到输出

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Day 42 算法记录|动态规划 09 (打家劫舍)

打家劫舍 198.打家劫舍213.打家劫舍II337.打家劫舍 III 198.打家劫舍 1.dp[i]&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房屋&#xff0c;最多可以偷窃的金额为dp[i]。 2.dp[i] max(dp[i - 2] nums[i], dp[i - 1]); 3.初始化&#xff0c;dp[0] 和 dp[1]&…

2021 年高教社杯全国大学生数学建模竞赛 E 题 中药材的鉴别 第一题

目录 1.数据预处理 1.1 数据基本信息探索 1.2 数据可视化 1.3 异常值处理 2. 数据特征值提取 2.1 数据标准化 2.2 PCA提取特征值 3. 数据聚类鉴别药材种类 3.1 肘部图确定K值 3.2 轮廓系数图确定K值 3.3 数据聚类 3.4 聚类结果可视化 4. 研究不同种类药材…

(10)强化:贪婪模式,捕获组,正则替换,正则分割,反向引用,UBB,断言,委托,Invoke,lambda,Action

一、作业问题 1、问&#xff1a;.net正则表达式默认使用unix的正则表达式模式? 答&#xff1a;在C#和.NET中&#xff0c;默认使用的是基于ECMAScript标准的正则表达式模式&#xff0c;而不是UNIX风 格的正则表达式模式。 …

MATLAB与ROS联合仿真——ROS环境搭建及相关准备工作(下)

本篇文章主要介绍在安装完ROS后&#xff0c;在进行MATLAB与ROS联合仿真之前&#xff0c;需要进行的一些环境搭建以及准备工作&#xff0c;主要分为 创建ROS工作空间及功能包、必备功能包安装、安装Gazebo11、导入实验功能包至工作空间、安装Visual_Studio_Code(选做)、常用便捷…

数据结构————顺序表

1.线性表 &#xff08;1&#xff09;.线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表&#xff0c;链表&#xff0c;栈&#xff0c;队列&#xff0c;字符串... &#xff08;2&#xff09;.线…

如何学习python数据分析?

Python数据分析基础全流程攻略如下&#xff08;适合初学、转岗、无编程基础小白&#xff0c;直接教学&#xff0c;没有额外链接&#xff09; 一、学习 针对数据分析模块&#xff0c;python学习的内容并非全都要学&#xff08;SQL也是如此&#xff09;&#xff0c;即不需要像程…

IT技术岗位应聘的关键技巧与准备方法

面试攻略&#xff1a; # 导入所需的模块 import pandas as pd import numpy as np# 定义一个函数&#xff0c;返回两个数字的和 def add_numbers(num1, num2):return num1 num2# 创建一个DataFrame data {"Name": ["Alice", "Bob", "Char…

新零售数字化商业模式如何建立?新零售数字化营销怎么做?

随着零售行业增速放缓、用户消费结构升级&#xff0c;企业需要需求新的价值增长点进行转型升级&#xff0c;从而为消费者提供更为多元化的消费需求、提升自己的消费体验。在大数据、物联网、5G及区块链等技术兴起的背景下&#xff0c;数字化新零售系统应运而生。 开利网络认为&…

微服务笔记---Nacos集群搭建

微服务笔记---Nacos集群搭建 Nacos集群搭建1.集群结构图2.搭建集群2.1.初始化数据库2.2.下载nacos2.3.配置Nacos2.4.启动2.5.nginx反向代理2.6.优化 Nacos集群搭建 1.集群结构图 官方给出的Nacos集群图&#xff1a; 其中包含3个nacos节点&#xff0c;然后一个负载均衡器代理…

实现Aware接口使用Spring底层组件

实现Aware接口使用Spring底层组件 Aware接口的实现类 基于Component&#xff0c;通过Aware的实现类在容器创建之前将Spring底层的信息获取并使用。 例如&#xff1a; 获取应用上下文对象applicationContext的ApplicationContextAware获取该类的bean对象信息的BeanNameAware…

企业资产管理,这么用事半功倍!

在当今竞争激烈的商业环境中&#xff0c;有效地管理和追踪资产&#xff0c;对于实现高效运营、优化资源利用和降低成本至关重要。 资产管理系统的引入&#xff0c;不仅可以提高资产管理的透明度和准确性&#xff0c;还可以加强对资产生命周期的控制&#xff0c;从而使企业在日常…

Zabbix监控之分布式部署

文章目录 Zabbix监控之分布式部署zabbix proxy概述部署zabbix-proxy节点规划基础环境准备安装proxy以及数据库配置数据库添加服务端host解析修改zabbix-proxy配置文件启动代理服务器 zabbix页面(1)在zabbix页面添加代理(2)zabbix-agent连接proxy Zabbix监控之分布式部署 zabbi…

Django校园宿舍管理系统【纯干货分享,免费领源码】

摘 要 本论文主要论述了如何使用django开发一个校园宿舍管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述校园宿舍管理系统的当前背景以及系统开发的目的…

脑电信号处理与特征提取——1. 脑电、诱发电位和事件相关电位(胡理)

目录 一、 脑电、诱发电位和事件相关电位 1.1 EEG基本知识 1.2 经典的ERPs成分及研究 1.2.1 ERPs命名规则及分类 1.2.2 常见的脑电成分 1.2.3 P300及Oddball范式 1.2.4 N400成分 一、 脑电、诱发电位和事件相关电位 1.1 EEG基本知识 EEG(Electroencephalogram)&#x…

爬虫001_Pip指令使用_包管理工具_pip的使用_和源的切换---python工作笔记019

scrapy是一个爬虫的框架 确认一下pip这个python中的包管理工具是否已经安装好了 python的环境变量配置完了以后,还需要配置一下pip的环境变量 把这个目录配置好,这个pip的环境变量的配置很简单不多说了. 我们用pip安装一下包,我们安装到上面这个路径里面,就是python的安装路…

生态系统模型:SolVES、DNDC、CMIP6、GEE林业、APSIM、InVEST、META分析、文献计量学、无人机遥感、ArcGIS Pro模型等

【原文链接】&#xff1a;【科研必备软件教程】气象、生态、遥感、水文、洪水、语言、人工智能、地质等领域模型应用https://mp.weixin.qq.com/s/KgSvl20fIjTY0ZWDyF0-8A 【目录】&#xff1a; R语言在生态环境领域中的实践技术应用 CENTURY模型实践技术应用与案例分析 生态…

docker 禅道 不使用自建数据库 使用自定义数据库

网上关于docker 禅道使用非自带数据库资料好少&#xff0c;所以记录下&#xff0c;希望能帮助更多的人。 据说&#xff1a; 其他镜像都是内置了数据库&#xff0c; 如果使用外置的数据库&#xff0c;可以使用这个镜像 ​easysoft/quickon-zentao ​ 以上未知真伪&#xff…

视频的音频提取怎么做?这样提取很简单

提取视频中的音频通常在需要从视频中独立使用音频或需要对音频进行编辑时使用。例如&#xff0c;当我们需要将音频上传到音乐流媒体平台或将其用于播客或其他音频项目时&#xff0c;就可能需要从视频中提取音频。问题是该怎么提取呢&#xff1f;教给大家几种简单的提取方法&…