七、进程程序替换

news2024/11/30 2:27:26

文章目录

  • 一、进程程序替换
    • (一)概念
    • (二)为什么程序替换
    • (三)程序替换的原理
    • (四)如何进行程序替换
      • 1. execl
      • 2. 引入进程创建——子进程执行程序替换,会不会影响父进程呢?
    • (五)大量的测试各种不同的接口
      • 1.命名理解 (带v和带l的)
      • 2.记忆技巧
      • 3.带e和带p
    • (六)具体接口说明
      • 1.execv
      • 2.execlp
      • 3.execvp
      • 4.execle
  • 二、模拟实现shell
  • 三、内建命令——以chdir为例

一、进程程序替换

(一)概念

子进程执行的是父进程的代码片段,如果我们想让创建出来的子进程,执行全新的程序呢?

需要用到:进程的程序替换!

(二)为什么程序替换

我们一般在服务器设计(linux编程)的时候,往往需要子进程干两件种类事情!

  1. 让子进程执行父进程的代码片段(服务器代码)
  2. 让子进程执行磁盘中一个全新的程序(shell,想让客户端执行对应的程序,通过我们的进程,执行其他人写的进程代码等等),c/c++ ->c/c++/Python/Shell/Php/Java…

(三)程序替换的原理

  1. 将磁盘中的程序,加载入内存结构
  2. 重新建立页表映射,谁执行程序替换,就重新建立谁的映射(子进程)

效果:让我们的父进程和子进程彻底分离,并让子进程执行一个全新的程序!

在这里插入图片描述

这个过程有没有创建新的进程呢?

没有,子进程的PCB等结构并未改变,只是改变的页表映射关系。

程序替换成功后,运行完新程序,则程序直接退出;程序替换成功后,原进程没有退出,使用原进程运行新程序

我们只能调用接口,为什么呢?

因为这个过程实际上是把数据从一个硬件搬到另一个硬件的操作,这个操作只能由OS操作系统完成

(四)如何进行程序替换

man execl 查看进行程序替换的函数:
我们如果要执行一个全新的程序,我们需要做几件事情呢?

1.程序本质就是一个磁盘上的文件,所以我们需要先找到这个程序在哪里
2.程序可能携带选项进行执行(也可以不携带),然后告诉OS,我要怎么执行这个程序?(要不要带选项)

命令行怎么写(ls -l -a), 这个参数就怎么填"ls",“-l”,“-a”,最后必须是NULL,标识参数传递完毕[如何执行程序的]
00

 #include <unistd.h>

       extern char **environ;

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

1. execl

makefile

myexec:myexec.c
	g++ -o $@ $^ -std=c++11 
.PHONY:clean
clean:
	rm -f myexec

myexec.c

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc,char *argv[]) {
    printf("process is running...\n");
    pid_t id  = fork();
    assert(id != -1);
    if (id == 0) {
        sleep(1);
        printf("我是一个进程,我的pid是:%d\n",getpid());
        // 执行ls -l -a 命令
        //execl("/usr/bin/ls","ls","-l","-a",NULL); 
        // 这里有两个ls, 重复吗?不重复,一个是告诉系统我要执行谁?一个是告诉系统,我想怎么执行
        // 执行top命令
        execl("/usr/bin/top","top",NULL);               
        
        printf("我执行完毕了,我的pid是:%d\n",getpid());      

        // 执行完以上的代码,我们发现一个问题!!
        // 最后一句代码为什么没有被打印出来呢!!!
    }
    return 0;
}

在这里插入图片描述
因为进程一旦替换成功,是将当前进程的代码和数据全部替换了!!!

后面的printf是代码吗??有没有被替换呢??当然,已经早就被替换了!!该代码不存在了!!

所以这个程序替换函数,用不用判断返回值?为什么?

答:不用判断返回值,因为只要成功了,就不会有返回值execl,一旦替换成功,是将当前进程的所有代码和数据全部替换了,execl就直接执行ls命令的代码去了。。而失败的时候,必然会继续向后执行!!最多通过返回值得到什么原因导致的替换失败!

2. 引入进程创建——子进程执行程序替换,会不会影响父进程呢?

子进程执行程序替换,会不会影响父进程呢? ?

不会,因为进程具有独立性。
为什么,如何做到的? ?数据层面发生写时拷贝!当程序替换的时候,我们可以理解成为:代码和数据都发生了写时拷贝完成父子的分离!

(五)大量的测试各种不同的接口

1.命名理解 (带v和带l的)

这些函数原型看起来很容易混,但只要掌握了规律就很好记。

l(list) : 表示参数采用列表

v(vector) : 参数用数组

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

e(env) : 表示自己维护环境变量

2.记忆技巧

execl结尾 l 为list,列表传参——>可变参数包,一个一个传。

execv结尾 v 为vector,数组传参——>传的是指针数组。

3.带e和带p

带e的都是可以传环境变量的(execle,execvpe)但是会覆盖系统原有的环境变量,把自己传的环境变量交给进程;
不带e是默认继承系统的环境变量;带p的都是可以自带路径的,直接传命令名称即可(execlp,execvp,execvpe)

(六)具体接口说明

1.execv

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

path 依然是程序的路径,参数 argv[] 是存着要实现指令的指针数组
在这里插入图片描述

char *const argv_[] = {
	  "ls",
      "-a",
       "-l",
       "--color=auto",
        NULL
};

2.execlp

int execlp(const char *file, const char *arg, ...);        带p的就传程序名即可

file:要执行的程序。执行指令的时候,默认的搜索路径,在哪里搜索呢?在环境变量PATH
命名带p的,可以不带路径,只说出你要执行哪一个程序即可!

execlp("ls""ls", "-a", "-1 "NULL)
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc,char *argv[]) {
    printf("process is running...\n");
    pid_t id  = fork();
    assert(id != -1);
    if (id == 0) {
        sleep(1);
        printf("我是一个进程,我的pid是:%d\n",getpid());
        //execl("/usr/bin/ls","ls","-l","-a",NULL); 
        // 这里有两个ls, 重复吗?不重复,一个是告诉系统我要执行谁?一个是告诉系统,我想怎么执行
        // 执行top命令
        char *const argv_[]={
        (char*)"ls",
        (char*)"-a",
        (char*)"-l",
         NULL
         };
        //execl("/usr/bin/top","top",NULL);         
        execlp("ls","ls","-a","-l",NULL);//这里出现了两个ls,含义一样吗?不一样!
        exit(1);   
        //execvp("ls", argv_);
        printf("我执行完毕了,我的pid是:%d\n",getpid());      

        // 执行完以上的代码,我们发现一个问题!!
        // 最后一句代码为什么没有被打印出来呢!!!
    }
    int status = 0;
    int ret = waitpid(id,&status,0);
    if(ret == id)
    {
        sleep(2);
        printf("父进程等待成功!\n");
    }
    return 0;
}

在这里插入图片描述

3.execvp

 int execvp(const char *file, char *const argv[]);
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc,char *argv[]) {
    printf("process is running...\n");
    pid_t id  = fork();
    assert(id != -1);
    if (id == 0) {
        sleep(1);
        printf("我是一个进程,我的pid是:%d\n",getpid());
        //execl("/usr/bin/ls","ls","-l","-a",NULL); 
        // 这里有两个ls, 重复吗?不重复,一个是告诉系统我要执行谁?一个是告诉系统,我想怎么执行
        // 执行top命令
        char *const argv_[]={
        (char*)"ls",
        (char*)"-a",
        (char*)"-l",
         NULL
         };
        //execl("/usr/bin/top","top",NULL);         
        //execlp("ls","ls","-a","-l",NULL);//这里出现了两个ls,含义一样吗?不一样!
        exit(1);   
        execvp("ls", argv_);
        printf("我执行完毕了,我的pid是:%d\n",getpid());      

        // 执行完以上的代码,我们发现一个问题!!
        // 最后一句代码为什么没有被打印出来呢!!!
    }
    // 父进程
    int status = 0;
    int ret = waitpid(id,&status,0);
    if(ret == id)
    {
        sleep(2);
        printf("父进程等待成功!\n");
    }
    return 0;
}

在这里插入图片描述

4.execle

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

这里的前几个接口都非常熟悉了,这里最后一个接口叫做环境变量。那么为什么要有这个接口呢?

说到环境变量之前我们先来看一下这个问题,我们刚刚提到过,进程替换可以让我们执行其他语言写的程序,那么我们怎么来执行呢?(我们使用execl 函数来调用)

我们现在的目标是想用我们写的myexec.c把mycmd.cpp调用起来,那么怎么来用呢?
myexec.c

我们当前使用的是绝对路径来调用我的mycmd程序!

当然我们也可以使用相对路径来调用。

相对路径调用——
makefile

.PHONY:all
all: mybin myexec
mybin:mybin.c
	g++ -o $@ $^ -std=c++11
myexec:myexec.c
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -f myexec mybin
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>

int main()
{
    printf("我是一个进程,我的pid是:%d\n",getpid());
    pid_t id=fork(); 
    if(id==0)
    {
        //child
        printf("我是子进程,我的pid是:%d\n",getpid());
        execl("./mycmd","mycmd",NULL);
        exit(1);
    }
    //一定是父进程
    int status=0;
    int ret=waitpid(id,&status,0);
    if(ret==id)
    {
        sleep(2);
        printf("父进程等待成功!\n");
    }

    return 0;
}

在这里插入图片描述
为什么会有这么多接口?——因为要适配应用场景。

execve为什么是单独的?——实际上,只有 execve是系统调用,其他都是对系统接口的封装,最后都要调用到execve!
在这里插入图片描述

二、模拟实现shell

三、内建命令——以chdir为例

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

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

相关文章

node.js卸载、安装、配置详解

node.js卸载、安装、配置详解 一、 node.js卸载二、下载安装2.1 下载2.2 安装2.2.1 选择msi安装2.2.2 选择zip安装 三、配置3.1 环境变量配置3.2 修改缓存、全局模块路径3.3 全局安装3.4 设置淘宝镜像3.5 全局安装 四、node-red安装及配置 一、 node.js卸载 第一步&#xff1a…

Salesforce顾问如何实现逆袭成为公司CIO?

Salesforce是一个适用于所有业务流程的绝佳平台&#xff0c;它的设置方式意味着使用者可以培养出独特的技能。其中一些从业者非常适合担任高管&#xff0c;Trailblazers通常会晋升到高层职位。 本文将帮助Trailblazers了解职位晋升需要的能力&#xff0c;为Salesforce之旅做好…

【大数据原理与技术】期末习题总结大全,建议收藏

【大数据原理与技术】期末习题总结大全&#xff0c;建议收藏 &#x1f4e2;&#x1f4e2;题目来源于B站&#xff0c;慕课网&#xff0c;百度 &#xff0c;适用于期末复习&#xff0c;内容仅供参考&#xff0c;祝大家考试顺利&#xff01; &#x1f4e2;以下思维导图我是根据我们…

LiveGBS国标GB/T28181流媒体平台功能-作为下级国标平台级联到第三方海康大华宇视华为等国标平台及其它政务公安内网国标视频平台

LiveGBS国标GB/T28181流媒体平台功能-作为下级国标平台级联到第三方海康大华宇视华为等国标平台及其它政务公安内网国标视频平台 1、GB/T28181级联是什么2、搭建GB28181国标流媒体平台3、获取上级平台接入信息3.1、如何提供信息给上级3.2、上级国标平台如何添加下级域3.2、接入…

固定翼、免像控、相对精度优于10cm,农村不动产项目验证

前言 在航测外业作业中&#xff0c;布设相控点应该是耗时最多的工作&#xff0c;繁琐而辛苦。本次&#xff0c;中水成勘院联合成都睿铂&#xff0c;以睿铂DG4pros五镜头倾斜相机为载荷&#xff0c;纵横CW10型固定翼无人机为载机&#xff0c;共同进行免像控相对精度项目验证。希…

软件测试常见的20个误区,你真的了解吗?

常见的20个误区 今天分享软件测试中常遇到的 20 个误区&#xff0c;争取能给想从事软件测试的小伙伴一点启发。 1、测试人员不需要了解软件开发知识 抛开自动化测试&#xff0c;测试开发等&#xff0c;这些是必须要学习软件开发知识。功能测试和接口测试等还是需要软件开发知…

VUE3-组件问题

VUE3-组件问题 文章目录 VUE3-组件问题一、S-Table1.问题描述2.问题展示3.问题解决 二、form表单无法显示1.问题描述2.问题展示3.问题解决 一、S-Table 1.问题描述 一个页面存在两个S-table&#xff0c;经检查均无误&#xff0c;第一个S-Table刷新可用&#xff0c;第二个刷新…

迷茫了5年:做完这个测试项目,我终于决定跳槽!

2023年早已过半&#xff0c;来个迟到的年中总结&#xff0c;说实话&#xff0c;2023&#xff0c;很迷茫&#xff0c;然后过的非常不如意&#xff0c;倒不是上一年的职业目标没达到&#xff0c;而是接下来的路根本不知道如何走。在没解决这个问题之前&#xff0c;或者说没搞清楚…

numpy知识点总结

numpy 基本介绍 ufunc 接口方法的基础 reduce&#xff0c;聚合方法 accumulate&#xff0c;累计聚合 reduceat&#xff0c;按指定轴向、指定切片聚合 outer&#xff1a;外积 ndarray 数据结构的基础 数组的创建 特定的函数结构 从特定库函数创建 random系列 特定的结构创建数…

9. 支持向量机(SVM)

9.1 优化目标 在逻辑回归中做一些小改动变成支持向量机。 如果观察逻辑回归的代价函数&#xff0c;会发现每个样本(x,y)都会为总的代价函数增加如下图这一项。因此对于总的代价函数&#xff0c;我们通常对所有的训练样本从第1项到第m项进行求和。 图中的这一表达式就代表每个单…

CnOpenData小巨人和单项冠军企业专利及引用被引用数据

一、数据简介 专精特新”一词最早来源于2011年7月&#xff0c;由时任工信部总工程师朱宏任在《中国产业发展和产业政策报告&#xff08;2011&#xff09;》新闻发布会上首次提出。“专精特新”是指具备专业化、精细化、特色化、创新型四大优势的企业。根据工信部的定义&#xf…

单层玻璃隔断移门轨道滑轮如何安装

在家居装修中&#xff0c;隔断是不可或缺的一部分。而单层玻璃隔断因其时尚美观和装修效果好&#xff0c;备受人们的喜爱。在单层玻璃隔断中&#xff0c;移门轨道和滑轮的选择及安装也是至关重要的一环。下面&#xff0c;阁瑞活动隔断就为大家详细介绍一下单层玻璃隔断移门轨道…

javaScript蓝桥杯----年度明星项⽬

目录 一、介绍二、准备三、⽬标四、代码五、完成 一、介绍 作为前端开发的主⼒语⾔&#xff0c; JavaScript 相关的开源项⽬是每⼀个前端开发者都应该多多关注的。我们可以通过这⼀年新增 star 的数量来判断⼀个开源项⽬的流⾏趋势。 本题请实现⼀个展示 2022 年 JavaScript 明…

【MySQL数据库 | 第六篇】DDL操作 表

目录 &#x1f914;前景知识&#xff1a; 数据类型&#xff1a; 1. 数值类型 2. 字符串类型 3. 日期时间类型 &#x1f914;DDL操作表&#xff1a; 1.创建 示例&#xff1a;尝试创建把以下实例创建到表里 2.查询 1.查询当前数据库的所有表&#xff1a; &#x1f50…

Ai前沿技术汇总[1]:Quivr非结构化信息搜索、Drag Your GAN AI修图、MiniGPT-4、Falcon-40B、localGPT

“AI前沿技术”专栏汇集了最前沿的人工智能技术&#xff0c;包括自然语言处理、语音识别、图像识别、机器学习、深度学习、强化学习、计算机视觉、区块链技术、智能机器人技术和虚拟现实技术等。本专栏将带您了解人工智能领域的最新进展和研究成果&#xff0c;探索人工智能技术…

软件测试的案例分析 - 闰年4.2 (加投票)

这篇博客的目录 文章目的正文错误之一出错后怎么改正&#xff1f;正确而简明的算法 文章目的 显示不同的博客能获得多少博客质量分 &#xff08;这是关于博客质量分的测试 https://www.csdn.net/qc) 这个博客得了 60 分。 希望在新的质量分系统中&#xff0c;获得 80 - 90 分左…

NoSQL数据库

NoSQL数据库 NoSQL简介NoSQL兴起的原因NoSQL与关系数据库的对比NoSQL的四大类型键值数据库列族数据库文档数据库图形数据库不同类型数据库比较分析RedisMongoDBCassandraNeo4j NoSQL三大基石CAPBASE最终一致性 NoSQL简介 “Not Only SQL”泛指非关系型的数据库&#xff0c;区别…

简单分享怎么通过微信小程序开店

小程序开店的好处 1.可以为用户提供更多的便利。通过使用微信或其他社交媒体&#xff0c;可以随时随地与潜在客户进行交流互动。 2.让消费者体验更好。通过二维码、小程序代码等方式&#xff0c;消费者能够快速找到所需产品和服务。 3.有助于降低营销成本。相比传统销售渠道…

关于Idea的一些常用设置项

1. 输出中文不乱码 设置工程项目编码 file -> settings -> Editor -> File Encodings-> 如下图通通UTF-8 2. 创建文件自动设置本文模板 File–>settings–>Editor–>File and Code Templates–>Includes -> 输入类注释模板 /*** Classname ${N…

第9章:SpringMVC的拦截器

一、拦截器 1.拦截器的配置 SpringMVC中的拦截器用于拦截控制器方法的执行SpringMVC中的拦截器需要实现HandlerInterceptorSpringMVC的拦截器必须在SpringMVC的配置文件进行配置 ①创建拦截器&#xff0c;继承接口HandlerInterceptor. Component public class FirstIntercep…