Linux进程控制(下)--->进程程序替换

news2024/10/6 14:32:58

文章目录

    • 什么是进程程序替换
    • 为什么要进行进程程序替换
    • 怎么进行进程程序替换
      • execl
      • execv
      • execlp
      • execvp
      • execle
      • execvpe
    • 使用c的可执行程序调用一个python脚本
    • 如何理解进程程序替换
      • 进程程序替换接口的返回值
      • 从进程独立性体会程序替换

什么是进程程序替换

在讲进程程序替换之前,首先我们先回顾一下我们先前学习的内容:
在前面的学习里面,我们学会了使用fork系统调用来进行子进程的创建。并且我们知道,子进程的大多数属性继承自父进程。 这就意味着,子进程会重复做和父进程一样的事情。即使使用if和else控制,但是这一部分仍然属于是父进程的部分! 显然,如果我们只是单纯地让子进程重复父进程的行为是没有任何实际应用价值的! 那么我们渴望一种方式,能够让子进程做和父进程不一样的事情!
而这样的一种方式就是进程程序替换

为什么要进行进程程序替换

除了让子进程的能够执行和父进程不同的事情以外。有的场景下,c++开发组需要使用python开发组提供的某种组件,但是由于语言之间的不能直接兼容,所以往往需要第三方工具做转换。而比较简单的方式就是使用进程程序替换的方式完成跨语种的调用! 所以在跨语种的调用的时候,进程程序替换也是一种较好的方式。

怎么进行进程程序替换

前面我们讲了一系列的有关进程程序替换的概念和好处。接下来我们就来见一见猪跑 来使用一下Linux系统提供的进程程序替换接口。
下面是Linux进程程序替换接口:

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 execvpe(const char *file, char *const argv[],
char *const envp[]);

接下来我们就来详细看一看这些接口如何使用

execl

首先我们先来看第一个接口:execl,对应的函数声明如下

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

在C语言里面,…代表的是可变参数列表。即这个参数可以带上不限数目的参数。下面我们就来对这个接口的两个参数进行解读。

path:路径:就是告诉被替换的进程要去执行那一个程序,要执行一个程序的前提是要找到这个程序!
args:执行程序的方式:选项参数

接下来我们使用代码执行ls命令

#include<stdio.h>
#include<unistd.h>
/*
 * 进程程序替换--->替换成ls -l
 * */

int main()
{ 
   printf("我是一个进程我的pid是%d\n",getpid());
   //最后必须一NULL结尾
   execl("/usr/bin/ls","ls","-l",NULL);
   //程序替换以后是否会执行这句代码呢?
   printf("我是一个进程,我的pid是%d\n",getpid());
  return 0;
}

执行结果如下:
在这里插入图片描述
从运行的结果来看,后续的打印代码并没有执行. 而对于这一现象我们会在后面详细解析。或许你会觉得这样使用这个接口太麻烦了,而实际上,官方还给我们提供了一系列更简便的方式来进行程序替换。接下来我们再来看下面的接口

execv

老规矩,先从官方文档里面来看函数的声明

int execv(const char *path, char *const argv[]);
参数解析:1.第一和先前一样,指向我们的要替换程序的所在路径,第二个参数则是一个字符指针数组,指向的就是我们所要执行的命令和命令的选项

#include<stdio.h>
#include<unistd.h>
/*
 *进程程序替换 ,依旧是执行ls相关的代码
 * execv
 * */ 
int  main()
{
   char* args[]={
     (char*) "ls",
      (char*)"-a",
      (char*)"-l",
      NULL
  };
  execv("/usr/bin/ls",args);
  return 0;
}

执行结果也是一样的
在这里插入图片描述
也就是说,execl和execv仅仅只在传递参数上存在一些不同,其余都是一致的!而对于l和v的理解可以如下理解

L list, 是一个列表,所以是一个列表
V: vector, 是一个向量,所以是一个数组

但是聪明的你又会开始抱怨,每次都要告诉我这个进程去哪里替换这个程序。我大多数情况下替换的都是系统的命令,难道就不能让这个进程去默认的系统路径下找对应的命令。这样我只要告诉进程怎么执行这个新的程序的命令就好了。别急,接下来我们就来看一看程序替换接口里面能够自动搜索系统路径的接口

execlp

先来看一看函数的声明:

int execlp(const char *file, const char *arg, …);
参数解读:也是列表方式传参,而这里的第一个参数是对应的可执行程序的名字,接口的p就代表的是path,这个接口会从系统默认的可执行路径下寻找程序

#include<stdio.h>
#include<unistd.h>
/*
 *调用execlp调用,p是path的意思,带有p的进程程序替换接口
 都会默认从系统的路径进行查找
 * */
int main()
{  
  //这两个ls的意义不一样,前者说明我要执行那一个程序,后者是执行的方式
  //最后都要一NULL结尾
   execlp("ls","ls","-a","-l",NULL);
  return 0;
}

在这里插入图片描述

execvp

这个接口和execlp类似,也会从默认的系统路径下搜索,仅仅是传参的方式不同罢了。

#include<stdio.h>
#include<unistd.h>
/*
 
 *调用execvp调用,p是path的意思,带有p的进程程序替换接口
 都会默认从系统的路径进行查找,用法和execlp基本类似
 * */
int main()
{
  char* agrc[]={
    (char*)"ls",
    (char*)"-a",
    (char*)"-l"
  };
  execvp("ls",agrc);
  return 0;
}

运行结果就不在演示了,和前面的execlp的效果是一样的。接下来,我们就来介绍最后的两个接口,带了一个e版本的进程替换接口

execle

末尾带e的进程程序替换接口允许我们自定义环境变量,下面我们就来简单用一用这个样例代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{ //使用C语言自带的环境变量,替换对应的c++程序
  extern char** environ;
  execle("./test_execle","./test_execle",NULL,environ);
 return 0;
}
//--------------------------------------
/*
 *仅仅是为了观察exelce环境变量的变化问题
 * */
#include<iostream>
#include<cstdlib>
int main()
{
  std::cout<<"替换成我以后,PATH是"<<getenv("PATH")<<"\n";  
  std::cout<<"替换成我以后,MYVALUE是"<<getenv("MYVALUE")<<"\n";  
  return 0;
}


在这里插入图片描述
我们可以看到这里我们的MYVALUE没有打印出来,原因是我们还没有把对应的环境变量导入,下面我们把对应的变量导入一下

export MYVALUE="测试环境变量"

导入完毕以后,对应的系统的打印结果如下。可以看到,这里我们的系统变量和path变量都打印出来了。
在这里插入图片描述
那么接下来,我们就尝试自己设置进程替换的环境变量

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<unistd.h>
int main()
{ /*
   自行设置环境变量
*/
  printf("我是一个C进程,我要替换一个C++程序\n");
  char* const env[]={
     (char*) "MYVALUE=测试环境变量",
       NULL
  };
  int ret=execle("./test_execle","./test_execle",NULL,env);
  printf("%d\n",ret);
  return 0;
}

运行结果:
在这里插入图片描述
可以看到,我们导入的环境变量是正常打印了,但是系统的环境
变量却找不到了!也就是说,这个环境变量的添加是覆盖式地写入!

所以我们在使用带e系列的接口的使用要特别注意环境变量覆盖式写入的问题。

execvpe

这个接口使用的方式和execle的方式相似,不过就是因为它带了一个p,所以我们可以直接指定替换的程序名字即可。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
/*
 * 使用execvpe接口,使用方式是execle类似,只不过不要自己带路径了
 * */

int main()
{ 
  printf("我是一个进程,我要使用进程程序替换接口了\n");
  extern char** environ;
   char* const arg[]={
   (char*)"ls",
   (char*)"-a",
   (char*)"-l",
   NULL 
  };
   char* const env[]={
       *environ,
        NULL
   };
   execvpe("ls",arg,env);
  return 0;
}

在这里插入图片描述

使用c的可执行程序调用一个python脚本

那么进程程序替换除了可以让父子进程执行不同的任务以外,另外一个用途就是可以用来跨语言调用,即用可以用一个cpp程序去替换一个python代码,我们准备如下的py脚本

#!usr/bin/python3
print('hello python')
print('hello python')
print('hello python')
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
/*
 *跨语言平台调用
 *
 * */
int main()
{
  printf("我是一个C语言写的程序,我跑起来就是一个进程,我要去替换一个python代码\n");
  //要执行的是/usr/bin/python3
  char* const argv[]={
     (char*)"python3",
     (char*)"./test.py",
      NULL,
  };
  execvp("python",argv);
  return 0;
}

运行结果如下:
在这里插入图片描述

如何理解进程程序替换

接下来,我们来深入谈一谈进程在进行程序替换的时候发生了什么。

进程程序替换接口的返回值

首先,细心的读者一定会注意到,这些进程程序替换都有一个返回值。先前我们使用其他的系统接口,我们都会特别注意返回值的判断,那么进程程序替换的返回值我们需要做判断吗?
并不需要! 因为一旦进程程序替换成功,当前的进程就去执行别人的代码了,根本就不会在返回我们这个进程继续执行了!这种情况下根本不会拿到对应的返回值,而一旦进程程序替换失败。那么我们就能拿到这个返回值,此时只要我们拿到这个返回值,必然已经是替换失败了。所以不必多此一举来判断返回值。

从进程独立性体会程序替换

接下来我们从进程的独立性和进程地址空间的角度来看待程序替换:
在这里插入图片描述
简单的一个结论;进程程序替换:替换的程序载入内存,写时拷贝代码段,重新修改页表映射关系


这就是本文的主要内容,如有不足之处,还望指出。

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

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

相关文章

[附源码]java毕业设计兰州市邮政公司新邮预订户管理信息系统

项目运行 环境配置&#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…

计算机毕业设计springboot+vue+elementUI在线漫画周边销售购物交流系统

项目介绍 任何系统都要遵循系统设计的基本流程&#xff0c;本系统也不例外&#xff0c;同样需要经过市场进行调研&#xff0c;漫画需求进行分析&#xff0c;概要设计&#xff0c;系统详细设计&#xff0c;测试和编码等步骤&#xff0c;设计并实现了“漫画之家”系统 。系统选用…

web前端设计与开发期末作品_期末大作业-疫情

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业&#xff0c;击疫情致敬逆行者感人类题材 | 致敬逆行者网页设计作品 | 大学生抗疫感动专题网页设计作业模板 | 等网站的设计与制作 | HTML期末大学生网页设计作业 HTML&#xff1a…

大一学生Web课程设计 红酒美食主题网页制作(HTML+CSS+JavaScript)

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 茶文化网站 | 中华传统文化题材 | 京剧文化水墨风书画 | 中国民间年画文化艺术网站 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运…

通用后台管理系统前端界面Ⅵ——首页、登录页、404页面

登录页 1、为了方便起见&#xff0c;先将element-ui的使用改为全局引入的方式。修改main.js文件如下&#xff1a; import Vue from vue import App from ./App.vue import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css //这个是局部引入&#xff0…

idea创建javaweb项目步骤超详细(2022最新版本)

目录 前言&#xff1a; 一、新建文件 1.在idea里面点击文件-新建-项目 2.新建项目-更改名称为自己想要的项目名称-创建 3.右键自己建立的项目-添加框架支持 4.勾选Web应用程序-确定 5.建立成功界面 二、配置tomcat 6.点击添加配置文件 7.点击这个 8.选择这个tomcat的本…

数据分析利器:XGBoost算法最佳解析

XGBoost是一种经典的集成式提升算法框架&#xff0c;具有训练效率高、预测效果好、可控参数多、使用方便等特性&#xff0c;是大数据分析领域的一柄利器。在实际业务中&#xff0c;XGBoost经常被运用于用户行为预判、用户标签预测、用户信用评分等项目中。XGBoost算法框架涉及到…

javaWeb项目基于tomcat运行部署后访问方案总结

javaWeb项目基于tomcat运行部署后访问方案总结 1.需求背景 最近接到一个老项目,这个是一个前后没有分离的java+jsp项目,所以前后端的代码是在一个项目里面的,因此在这个项目上开发就需要面临第一个问题:启动运行项目。简介:Java Web,是用Java技术来解决相关web互联网领域…

字符串的算法题目-字符串

题目一&#xff1a; 描述 对于一个长度为 n 字符串&#xff0c;我们需要对它做一些变形。 首先这个字符串中包含着一些空格&#xff0c;就像"Hello World"一样&#xff0c;然后我们要做的是把这个字符串中由空格隔开的单词反序&#xff0c;同时反转每个字符的大小写…

【Java】数组中值得说的那些事

文章目录前言一、数组的创建及初始化&#x1f333;1、数组的创建&#x1f333;2、数组的初始化&#x1f351;&#xff08;1&#xff09;动态初始化&#x1f351;&#xff08;2&#xff09;静态初始化二、数组的使用&#x1f333;1、数组中元素访问&#x1f333;2、遍历数组&…

力扣LeatCode算法题-两数之和(二)

力扣算法题第二题&#xff0c;两数相加算法题&#xff1a; 要求&#xff1a; //给出两个 非空 的链表用来表示两个非负的整数。其中&#xff0c;它们各自的位数是按照 逆序 的方式存储的&#xff0c;并且它们的每个节点只能存储 一位 数字。 //如果&#xff0c;我们将这两个数…

企业使用有线和5G主备双链路上网配置案例

场景介绍 典型的企业分支通常还是采用有线链路作为主链路&#xff0c;例如以太链路、MPLS专线等。为了提升分支站点的可靠性&#xff0c;企业一般都会部署两条上行链路&#xff0c;一条为主链路&#xff0c;一条为备链路。如果两条上行链路都采用有线&#xff0c;成本会比较高&…

JVM StringTable

文章目录学习资料StringTableString的基本特性String的内存分配StringTable为什么要调整&#xff1f;String的基本操作字符串拼接操作拼接操作与append操作的效率对比intern()的使用学习资料 【尚硅谷宋红康JVM全套教程&#xff08;详解java虚拟机&#xff09;】 【阿里巴巴Ja…

prometheus exporter 监控主机

前提要求部署Grafana 前言 有许多库和服务器可以帮助将第三方系统中的现有指标导出为Prometheus指标。在无法直接使用Prometheus度量(例如&#xff0c;HAProxy或Linux系统统计数据)对给定系统进行检测的情况下&#xff0c;这是非常有用的。 node-exporter Linux操作系统采集&…

【Hack The Box】windows练习-- Scrambled

HTB 学习笔记 【Hack The Box】windows练习-- Scrambled &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &…

第2-3-5章 删除附件的接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

文章目录5.4 接口开发-根据id删除附件5.4.1 接口文档5.4.2 代码实现5.4.3 接口测试5.4.4 测试ALI和FAST_DFS以及MINIO上传和删除的接口5.4.4.1 阿里云OSS上传和删除5.4.4.2 FastDFS上传和删除5.4.4.3 Minio上传和删除5.5 接口开发-根据业务类型/业务id删除附件5.5.1 接口文档5.…

[附源码]SSM计算机毕业设计成都团结石材城商家协作系统JAVA

项目运行 环境配置&#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…

力扣(LeetCode)6. Z 字形变换(C++)

数学构造 ZZZ 字形变换类似情报加密。找规律解密&#xff0c;就能得到构造的方法。 第 000 行相邻的数&#xff0c;取 n4n4n4 如上图&#xff0c;观察第 000 行和第 333 行 相邻的数&#xff0c;组成等差数列&#xff0c;公差 d62n−2d62n-2d62n−2 2n−22n-22n−2 是说 &…

【小程序】微信小程序云开发笔记详细教程(建议收藏)

1- 前言 1.1 微信云开发是什么&#xff1f; 微信云开发是微信团队联合腾讯云推出的专业的小程序开发服务。 开发者可以使用云开发快速开发小程序、小游戏、公众号网页等&#xff0c;并且原生打通微信开放能力。 开发者无需搭建服务器&#xff0c;可免鉴权直接使用平台提供的…

Spring Cloud | 实现Eureka Server 高可用服务注册中心全套解决方案

目录1、在搭建Eureka Server&#xff0c;配置高可用服务注册中心&#xff0c;配置3个Eureka Server:2、因为是在本地实现的话&#xff0c;需要在localhost加入三个服务&#xff0c;需要改变etc/hosts&#xff0c;linux系统通过vim /etc/hosts&#xff0c;3、如果是在测试或者是…