【Linux】进程控制之进程程序替换

目录

前言

替换的原理

替换函数

记忆技巧

函数使用

execl

execlp

execv

execvp 

execle

execvpe 

调用其它语言的程序

模拟实现一个shell


前言

关于本文可以先去看看上一篇【Linux】进程控制详解-CSDN博客可以更好的理解这里的内容

学完本篇文章,你就可以自己设计一个mini版的shell解释器,还可以用你写自己的代码区执行其它语言的程序。

替换的原理

用fork创建子进程后执行的是和父进程相同的代码,但有可能需要执行不同的代码分支,那么子进程往往要调用一种exec系列函数以执行另一个全新程序。当进程调用一种exec系列函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec系列函数并不创建新进程,所以调用exec系列函数前后该进程的ID并未改变。

替换函数

返回值:如果调用成功则加载新的程序从启动代码开始执行,不在返回;调用失败则返回-1。

记忆技巧

  • l(list):表示参数采用列表
  • v(vector):表示参数采用数组
  • p(path):第一个参数path不用输入路径,给出命令名即可,它会在环境变量PATH当中搜索对应的命令
  • e(env):将自己维护的环境变量传递给需要替换的进程
函数名参数格式是否带路径是否使用当前环境变量
execl列表
execlp列表
execle列表否,需自己维护环境变量
execv数组
execvp数组
execvpe数组否,需自己维护环境变量

函数使用

一旦发生了替换,那么替换函数后面的代码就不会再执行了。

int main()
{printf("当前进程的开始代码\n");execl("/usr/bin/ls", "ls", "-a", "-l", NULL);printf("当前进程的结束代码\n");return 0:
}

 

注:在调用替换函数时末尾最好加上NULL代表结束。

虽然我们可以不用创建子进程来使用替换函数,但是我们创建了子进程,替换的进程就是子进程而父进程不受影响,那么父进程就可以聚焦在读取数据,解析数据,指派进程执行代码等功能了。 

execl

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());execl("/usr/bin/ls", "ls", "-a", "-l", NULL);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

 

execlp

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());execlp("ls", "ls", "-a", "-l", NULL);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

execv

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 16int main()
{pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());char* const _argv[NUM] = {(char*)"ls",(char*)"-a",(char*)"-l",NULL };execv("/usr/bin/ls", _argv);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

execvp 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 16int main()
{pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());//execl("/usr/bin/ls", "ls", "-a", "-l", NULL);//execlp("ls", "ls", "-a", "-l", NULL);char* const _argv[NUM] = {(char*)"ls",(char*)"-a",(char*)"-l",NULL };execvp("ls", _argv);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

execle

 mycmd.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char* argv[])
{if(argc != 2){printf("can not execute\n");exit(1);}printf("获取环境变量:MY_VALUE:%s\n", getenv("MA_VALUE"));if(strcmp(argv[1], "-a") == 0){printf("hello 我是a\n");}else if(strcmp(argv[1], "-b") == 0){printf("hello 我是b\n");}else {printf("defalut\n");}return 0;
}

myproc.c 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 16
const char* myfile = "/home/hjx/for_linuxtest/test43/mycmd";int main(int argc, char* argv[], char* env[])
{char* const _env[NUM] = {(char*)"MY_VALUE=332335454",NULL };pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());execle(myfile, "mycmd", "-a", NULL, _env);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

 

所以mycmd.c就拿到了这里的环境变量

execvpe 

和上面的类似就不再演示了

 其实系统调用的接口只有一个——execve

而以上介绍的函数是操作系统是为了满足不同的调用场景提供的基本封装。

调用其它语言的程序

print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if(id < 0){perror("fork");exit(2);//子进程创建失败}else if(id == 0){//子进程printf("子进程开始执行,pid:%d\n", getpid());execlp("python", "python", "test.py", NULL);exit(1);//替换失败则终止进程}else {//父进程printf("父进程开始执行,pid:%d\n", getpid());int status;pid_t wid = waitpid(-1, &status, 0);//阻塞等待if(wid > 0){printf("wait success, exit code:%d\n", WEXITSTATUS(status));}}return 0;
}

模拟实现一个shell

有了上面的这些知识,那么我们可以自己设计一个简易版的shell。

shell代码链接:minishell

效果展示


今天的分享就到这里了,如果内容有错的话,还望指出,谢谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI智能分析盒子在工地的应用,提高工地管理效率和安全性

工地ai智能分析盒子是一种基于人工智能视觉分析技术的人工智能盒子&#xff0c;旨在提升工地作业区域的管理效率和保障作业人员的安全。通过最前沿的AI视觉算法、大数据&#xff0c;能够实时监控工地现场视频流画面&#xff0c;对施工工地人员的工作着装及日常作业行为进行规范…

OpenCV 4.9基本绘图

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV使用通用内部函数对代码进行矢量化 下一篇:使用OpenCV4.9的随机生成器和文本 ​目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 line() 画一…

产品经理和项目经理的区别

1. 前言 本文深入探讨了产品经理与项目经理在职责、关注点以及所需技能方面的显著区别。产品经理主要负责产品的规划、设计和市场定位,强调对用户需求的深刻理解和产品创新的推动;而项目经理则侧重于项目的执行、进度控制和资源管理,确保项目按时、按质、按预算完成。两者在…

一文搞懂从爬楼梯到最小花费(力扣70,746)

文章目录 题目前知动态规划简介动态规划模版 爬楼梯一、思路二、解题方法三、Code 使用最小花费爬楼梯一、思路二、解题方法三、Code 总结 在计算机科学中&#xff0c;动态规划是一种强大的算法范例&#xff0c;用于解决多种优化问题。本文将介绍动态规划的核心思想&#xff0c…

CTK插件框架学习-服务工厂(06)

CTK插件框架学习-信号槽(05)https://mp.csdn.net/mp_blog/creation/editor/137240105 一、服务工厂定义 注册插件时使用服务工厂注册&#xff0c;使用getService根据调用者插件资源文件内容获取在服务工厂内的对应实现在服务工厂中可以知道是哪个插件正在调用服务工厂懒汉模式…

rabbitmq死信交换机,死信队列使用

背景 对于核心业务需要保证消息必须正常消费&#xff0c;就必须考虑消费失败的场景&#xff0c;rabbitmq提供了以下三种消费失败处理机制 直接reject&#xff0c;丢弃消息&#xff08;默认&#xff09;返回nack&#xff0c;消息重新入队列将失败消息投递到指定的交换机 对于核…

代码随想录第34天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 贪心算法&#xff0c;这不就是常识&#xff1f;还能叫贪心&#xff1f;LeetCode&#xff1a;1005.K次取反后最大化的数组和_哔哩哔…

10.枚举

1.背景及定义 枚举是在JDK1.5以后引入的。 主要用途是&#xff1a; 将一组常量组织起来&#xff0c; 在这之前表示一组常量通常使用定义常量的方式&#xff1a; public static final int RED 1; public static final int GREEN 2; public static final int BLACK 3; 但是…

Web Component 组件库有什么优势

前言 前端目前比较主流的框架有 react&#xff0c;vuejs&#xff0c;angular 等。 我们通常去搭建组件库的时候都是基于某一种框架去搭建&#xff0c;比如 ant-design 是基于 react 搭建的UI组件库&#xff0c;而 element-plus 则是基于 vuejs 搭建的组件库。 可能你有这种体…

C语言进阶课程学习记录-第22课 - 条件编译使用分析

C语言进阶课程学习记录-第22课 - 条件编译使用分析 条件编译基本概念条件编译实验cmd命令窗口输入演示条件编译本质实验-ifdefcmd定义宏结果比较 include本质实验-间接包含同一个头文件解决重复包含的方法-ifndef实验-条件编译的应用小结 本文学习自狄泰软件学院 唐佐林老师的 …

线上研讨会 | 新一代数字化技术赋能机器人及智能产线行业高质量发展

随着智能制造的快速推进&#xff0c;制造业转型升级到了关键阶段。越来越多的企业以数字化技术搭配智能机器人及智慧产线&#xff0c;主动实现数字化转型。达索系统3D体验平台是实现企业数字化转型的新一代数智化平台&#xff0c;基于型、数字驱动、数字化连续技术&#xff0c;…

基于Socket简单的UDP网络程序

⭐小白苦学IT的博客主页 ⭐初学者必看&#xff1a;Linux操作系统入门 ⭐代码仓库&#xff1a;Linux代码仓库 ❤关注我一起讨论和学习Linux系统 1.前言 网络编程前言 网络编程是连接数字世界的桥梁&#xff0c;它让计算机之间能够交流信息&#xff0c;为我们的生活和工作带来便利…

ICLR24_OUT-OF-DISTRIBUTION DETECTION WITH NEGATIVE PROMPTS

摘要 分布外检测&#xff08;OOD Detection&#xff09;的研究对于开放世界&#xff08;open-world&#xff09;学习非常重要。受大模型&#xff08;CLIP&#xff09;启发&#xff0c;部分工作匹配图像特征和提示来实现文本-图像特征之间的相似性。 现有工作难以处理具有与已…

牛顿:Archetype AI 的开创性模型,实时解读真实世界的新宠儿

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

免费云服务器汇总,最长永久免费使用

随着云计算技术的快速发展&#xff0c;越来越多的企业和个人开始将业务迁移到云端。云服务器作为云计算的重要组成部分&#xff0c;以其灵活、高效、可扩展等特点受到广泛关注。然而&#xff0c;许多人在初次接触云服务器时&#xff0c;可能会对高昂的价格望而却步。为了帮助大…

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

【C++学习】哈希的应用—位图与布隆过滤器

目录 1.位图1.1位图的概念1.2位图的实现3.位图的应用 2.布隆过滤器2.1 布隆过滤器提出2.2布隆过滤器概念2.3如何选择哈希函数个数和布隆过滤器长度2.4布隆过滤器的实现2.4.1布隆过滤器插入操作2.4.2布隆过滤器查找操作2.4.3 布隆过滤器删除 2.5 布隆过滤器优点2.6布隆过滤器缺陷…

[BT]BUUCTF刷题第13天(4.1)

第13天 Upload-Labs-Linux (Basic) Pass-01 根据题目提示&#xff0c;该题为绕过js验证。 一句话木马&#xff1a; <?php eval(system($_POST["cmd"]));?> // 符号 表示后面的语句即使执行错误&#xff0c;也不报错。 // eval() 把括号内的字符串全部…

lottery-攻防世界

题目 flag在这里要用钱买&#xff0c;这是个赌博网站。注册个账号&#xff0c;然后输入七位数字&#xff0c;中奖会得到相应奖励。 githacker获取网站源码 &#xff0c;但是找到了flag文件但是没用。 bp 抓包发现api.php&#xff0c;并且出现我们的输入数字。 根据题目给的附…

未来的技术发展趋势

文章目录 前言一、人工智能技术势必聚焦安全能力二、单云环境逐渐让位于多云环境三、后量子密码或将在美大范围普及总结前言 2023 年,与网络空间安全息息相关的人工智能等技术发展迅猛,新的信息安全时代已然拉开大幕。在目睹了 ChatGPT、“星链”和量子通信等技术展现出的巨…