Linux操作系统学习(进程替换)
文章目录
- 进程替换
- 进程替换是什么?
- 替换的方法
- 进程替换
- 简易shell模拟
进程替换
进程替换是什么?
如下图所示:
进程替换就是,把进程B的代码和数据,替换正在执行的进程A的代码和数据在内存中的位置(若代码数据过多可能会改变页表),但进程A的整体部分不发生任何改变(task_struct、A进程地址空间等等)

其实就是用A进程的壳子执行B进程程序,不改变A进程的任何东西,只改变页表物理地址部分和内存中的数据和代码,不创建任何新的进程,并且子进程也不会退出。
替换的方法
一般用到以下六种函数
| #include <unistd.h> |
|---|
| int exec l(const char *path, const char *arg, …); |
| int exec lp(const char *file, const char *arg, …); |
| int exec le(const char *path, const char *arg, …,char *const envp[]); |
| int exec v(const char *path, char *const argv[]); |
| int exec vp(const char *file, char *const argv[]); |
| int exec ve(const char *path, char *const argv[], char *const envp[]); |
命名后缀:
l(list) : 表示参数采用列表
v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
e(env) : 表示自己维护环境变量
程序运行时的环境变量信息(函数不会给你自动继承父进程的环境变量,需要手动设置)
返回值:
若替换失败则返回-1,但其实可以不用检查返回值因为:
-
调用成功一定执行替换的程序
-
调用失败一定执行原本的程序
-
int execl(const char *path, const char *arg, …);
void test1() { pid_t id = fork(); if(id == 0) { printf("你好\n"); /*********************************************开始替换******************************************/execl("/usr/bin/ls","ls","-a","-l","-i",NULL); //你要执行谁,想怎么执行(在命令行怎么执行就怎么执行),可变参数列表以NULL结尾//或者想要执行自己的程序 execl("./当前路径或者 /.../...绝对路径","可执行程序名",NULL);/*********************************************替换完成/失败******************************************/printf("hello\n"); } sleep(1); printf("child exchange succeed\n"); }
- int execlp(const char *file, const char *arg, …);
void test2() {pid_t id = fork();if(id == 0){char* argv[] = {"ls","-a","-i","-l",NULL};//就是把可变参数列表以数组的形式传给execvprintf("exchange test2--->:\n"); /*********************************************开始替换******************************************/execv("/usr/bin/ls",argv); /*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n"); }
- int execle(const char *path, const char *arg, …,char *const envp[]);
void test3() {pid_t id = fork();if(id == 0){printf("exchange test3---->\n"); /*********************************************开始替换******************************************/execlp("ls","ls","-l","-a","-i",NULL);// 第一个你要执行的是谁但不用带路径,path会根据这个程序名去自动搜索它在什么位置,第二个是要怎么执行 /*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}
- int execvp(const char *file, char *const argv[]);
void test4() {pid_t id = fork();if(id == 0){printf("exchange test4---->\n");char* argv[] = {"ls","-a","-l","-i",NULL}; /*********************************************开始替换******************************************/execvp("ls",argv); //第一个参数告诉path要执行的程序他会自动去找路径,第二个参数从可变参数列表变为自定义数组 /*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n"); }
- int execle(const char *path, const char *arg, …,char *const envp[]);
void test5() {pid_t id = fork();if(id == 0){printf("exchange test5---->\n"); /*********************************************开始替换******************************************/char* env[] = {"my_env=hello",NULL};execle("./print","print",NULL,env);//最后一个参数env指定了新程序的环境列表。参数env对应于新程序的environ数组//传递自己的环境变量给print /*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}int main() {extern char** environ;for(int i = 0;environ[i];i++){if(environ[i] == "PATH")continue;//path显示的太多,这里屏蔽掉printf("%s\n",environ[i]);}return 0; }
- int execve(const char *path, char *const argv[], char *const envp[]);
void test6() {pid_t id = fork();if(id == 0){printf("exchange test5---->\n"); /*********************************************开始替换******************************************/char* argv[] = {"print",NULL};char* env[] = {"my_env=hello",NULL};execve("./print",argv,env); /*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}int main() {extern char** environ;for(int i = 0;environ[i];i++){if(environ[i] == "PATH")continue;printf("%s\n",environ[i]);}return 0; }


可以看出所有的函数都是在execve基础上封装的
进程替换
-
子进程需要替父进程执行一些任务就需要进程替换
-
进程替换只替换子进程在内存中的代码和数据,以及页表物理地址部分
-
进程替换不会创建新进程,不会退出子进程
-
虽然父子代码是共享的,但是进程替换会更改内存的代码和数据,所以要发生写实拷贝
-
fork创建子进程后,在代码中exec…只会替换子进程,因为进程具有独立性
程序替换的本质是把程序的代码数据加载到指定进程的上下文中
简易shell模拟
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>void myshell()
{char command[128];char* argv[64];while(1){command[0] = 0;printf("[awd@VM-16-4-centos myshell]----->"); //打印前缀 fflush(stdout); //刷新缓冲区fgets(command,128,stdin); //输入命令command[strlen(command) - 1] = 0; //先当作整个字符串存入command,-1是除去\n//fflush(stdout); //printf("%s\n",command);验证const char* set = " "; //设置分隔符argv[0] = strtok(command,set); //把字符串拆解成指令int i = 1; while( argv[i] = strtok(NULL,set) ) //类似strcpy,赋值到NULL退出i++;/*for(int j = 0;j < i;j++)printf("%s\n",argv[j]);验证*/if(strcmp(argv[0],"cd") == 0) //在子进程cd影响的只是子进程,所以要再父进程处理{if(argv[1])chdir(argv[1]);continue;}if(fork() == 0) //创建子进程{execvp(argv[0],argv); //替父进程执行这些指令exit(1); //若执行到这说明替换失败,设置退出码为1}waitpid(-1,NULL,0); //等待任意一个子进程结束int status = 0;if(strcmp(argv[0],"echo") == 0 && strcmp(argv[1],"$?") == 0) //打印退出码和终止信号printf("exit code:%d ,exit signal:%d \n",WEXITSTATUS(status),WTERMSIG(status));}}int main()
{myshell();return 0;
}

通过这个简易shell来把之前学到的总结一下
- 一般让子进程替父进程执行一些第三方命令,那么就需要用到 进程替换和fork
- 子进程每次执行结束需要进程等待,为了结束他的僵尸进程并获取它的退出信息(退出码、终止信号)
- 每次进程退出后又会重新创建子进程,所以echo $? 查看的是最近一次执行的退出码
- 证明了每一次命令行执行的指令都是一次进程,是基于bash为父进程创建的子进程
上面这个简陋shell综合了 :fork、进程替换函数、进程等待函数、进程退出函数、退出码/终止信号,加深了这些接口的理解
相关文章:
Linux操作系统学习(进程替换)
文章目录进程替换进程替换是什么?替换的方法进程替换简易shell模拟进程替换 进程替换是什么? 如下图所示: 进程替换就是,把进程B的代码和数据,替换正在执行的进程A的代码和数据在内存中的位置(若代码…...
【C++从入门到放弃】类和对象(中)———类的六大默认成员函数
🧑💻作者: 情话0.0 📝专栏:《C从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! 类和对…...
白盒测试重点复习内容
白盒测试白盒测试之逻辑覆盖法逻辑覆盖用例设计方法1.语句覆盖2.判定覆盖(分支覆盖)3.条件覆盖4.判定条件覆盖5.条件组合覆盖6.路径覆盖白盒测试之基本路径测试法基本路径测试方法的步骤1.根据程序流程图画控制流图2.计算圈复杂度3.导出测试用例4.准备测试用例5.例题白盒测试总…...
【13】linux命令每日分享——groupadd建立组
大家好,这里是sdust-vrlab,Linux是一种免费使用和自由传播的类UNIX操作系统,Linux的基本思想有两点:一切都是文件;每个文件都有确定的用途;linux涉及到IT行业的方方面面,在我们日常的学习中&…...
《第一行代码》 第十章:服务
一,在子线程中更新UI 1,新建项目,修改布局代码 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"&g…...
简单介绍编程进制
十进制 十进制的位权为 10,比如十进制的 123,123 1 * 10 ^ 2 2 * 10 ^ 1 3 * 10 ^ 0。 二进制 二进制的位权为 2,比如十进制的 4,二进制为 100,4 1 * 2 ^ 2 0 * 2 ^ 1 0 *2 ^ 0。 Java7 之前,不支…...
windows忘记开机密码怎么办
windows忘记开机密码怎么办 清除windows登录密码 清除windows登录密码简单方法 开机到欢迎界面时,按CtrlAltDelete两次,跳出帐号窗口,输入用户名:administrator,回车, 或者启动时按F8 选“带命令行的安全…...
SpringCloud:Eureka
目录 一、eureka的作用 二、搭建Eureka服务端 三、添加客户端 四、服务发现 提供者与消费者 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务) 服务消费者:一次业务中,调用其它微服务的服…...
如何获取或设置CANoe以太网网卡信息(SET篇)
CAPL提供了一系列函数用来操作CANoe网卡。但是,但是,首先需要明确一点,不管是获取网卡信息,还是设置网卡信息,只能访问CAPL程序所在的节点下的网卡,而不是节点所在的以太网通道下的所有网卡 关于第一张图中,Class节点下,有三个网卡:Ethernet1、VLAN 1.100、VLAN 1.200…...
【软件测试面试题】项目经验?资深测试 (分析+回答) 我不信你还拿不到offer......
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 在面试过程中&#…...
tensorflow lite简介-移动设备端机器学习
TensorFlow Lite 是一组工具,可帮助开发者在移动设备、嵌入式设备和 loT 设备上运行模型,以便实现设备端机器学习。 支持多平台 支持多种平台,涵盖 Android 和 iOS 设备、嵌入式 Linux 和微控制器。 原理/流程 工作原理或者使用流程就是上面…...
Node.js常用知识
1、什么是 Node.js 【】Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。浏览器是 js 的前端运行环境,node.js 是 js 的后端运行环境。他们都有 V8 引擎,有各自的内置 API 2、fs 文件系统模块 【】fs 模块是 Node.js 官方提供的、用来操作文件…...
踩坑:maven打包失败的解决方式总结
Maven打包失败原因总结如下: 失败原因1:无法使用spring-boot-maven-plugin插件 使用spring-boot-maven-plugin插件可以创建一个可执行的JAR应用程序,前提是应用程序的parent为spring-boot-starter-parent。 需要添加parent的包spring-boot…...
【C++】位图
文章目录位图概念位图操作位图代码位图应用位图概念 boss直接登场: 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中❓ 40亿个整数,大概就是16GB。40亿个字节大概就是4GB。 1Byt…...
蓝桥杯-考勤刷卡
蓝桥杯-考勤刷卡1、问题描述2、解题思路3、代码实现1、问题描述 小蓝负责一个公司的考勤系统, 他每天都需要根据员工刷卡的情况来确定 每个员工是否到岗。 当员工刷卡时, 会在后台留下一条记录, 包括刷卡的时间和员工编号, 只 要在一天中员工刷过一次卡, 就认为他到岗了。 现在…...
如何利用站内推广和站外推广提高转化率?
在如今的网络时代,拥有一个好的网站是非常重要的。但是,光有一个好的网站是不够的,为了达到我们的目标,需要不断地提高网站的转化率。而在实现这个目标的过程中,站内推广和站外推广是两个非常关键的因素。 站内推广是…...
Java多线程(三)——线程池及定时器
线程池就是一个可以复用线程的技术。前面三种多线程方法就是在用户发起一个线程请求就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。线程池就相当于预先创建好几个线程…...
Linux命令行安装Oracle19c教程和踩坑经验
安装 下载 从 Oracle官方下载地址 需要的版本,本次安装是在Linux上使用yum安装,因此下载的是RPM。另外,需要说明的是,Oracle加了锁的下载需要登录用户才能安装,而用户是可以免费注册的,这里不做过多说明。 …...
Linux常用命令等
目录 1.Linux常用命令 (1)系统命令 (2)文件操作命令 2.vim编辑器 3.linux系统中,软件安装 (1) rpm 安装,RedHat Package Manager (2)yum 安装 (3)源代码编译安装 1.Linux常用命令 Linux命令是非常多的,对于像嵌入式开发工程师,运维工程师需要掌握的命令是非常多的.对于…...
CEC2014:鱼鹰优化算法(Osprey optimization algorithm,OOA)求解CEC2014(提供MATLAB代码
一、鱼鹰优化算法简介 鱼鹰优化算法(Osprey optimization algorithm,OOA)由Mohammad Dehghani 和 Pavel Trojovsk于2023年提出,其模拟鱼鹰的捕食行为。 鱼鹰是鹰形目、鹗科、鹗属的仅有的一种中型猛禽。雌雄相似。体长51-64厘米…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...






