Linux进程等待 | 程序替换

news2024/9/20 19:40:54

进程终止

一个进程退出了,无非只有三种情况:

  1. 代码跑完了,结果正确
  2. 代码跑完了,结果不正确
  3. 代码没跑完,程序异常退出了

代码跑完了,我们可以通过退出码获取其结果是否正确,(这个退出码就是我们在main函数都是写上 return 0)。而进程没跑完,就出现异常退出了,那么退出码就是无意义的。


进程退出码

是什么:OS用来表示一个进程结束时候状态的一个数值。

规定:0表示代码正确,非0表示出错。那么退出的信息谁来读取?父进程读取进程的退出码。

查看:通过echo $? 查看进程的退出码(注意:这次最近一次进程退出的结果)

 在C语言中,sterror函数会提供特定的错误码信息

同时会提供一个全局的变量errno用于记录特地函数出错的结果,称为错误码。

这个全局码可以被strerror函数解析处错误的信息。

errno会记录最后一次函数的出错信息,可以手动清零。

 许多系统调用出错,就会设置errno。比如将read设置为非阻塞,如果读出错,可能真的出错了,也可能本轮没有读到数据,就可以通过errno判断是否为EAGAIN。

错误码VS退出码

  1. 错误码就是函数出错的原因,一般不会直接影响进程的结果。
  2. 退出码用来衡量进程退出的结果。

进程退出的方式

正常终止

  • return 
  • exit()
  • _exit()

异常退出

  • 信号终止

关于  exit和_exit的区别

exit是C语言提供的库函数,底层封装了系统调用。会引起一个进程正常退出,并且会将缓冲区刷新。而_exit是系统调用,也是引起进程正确退出,但不会将缓冲区刷新。

演示区别

本质的区别就是数据被保留在缓冲区中了,没有被刷新到外设上。

 


进程终止,内核做了什么?


进程=内核数据结构+进程代码 和 数据

进程终止后,释放代码+数据资源,OS会先将进程的状态修改会Z状态,等待父进程读取进程的退出信息。

随后将状态由Z修改为X,并且释放内核数据结构。


进程等待

什么是进程等待:

通过wait或者waitpid,(父进程)对子进程的资源进行回收的等待过程。

为什么进程等待:
1.解决僵尸问题带来的内存泄漏

2.必要时候,获取子进程的退出信息(退出码+退出信号)

如何等待:

  • wait()

通过系统调用函数,回收指定进程的资源。

返回值:成功返回等待成功的子进程,失败返回-1。

其中wait的参数为整形指针,用于接收退出信息。

演示:故意让子进程先退出,父进程再等待回收。

会看到子进程退出后,状态变为Z状态,随后立马被删除,也就是被父进程回收资源了

  •  waitpid
pid_t waitpid(pid_t pid, int *_Nullable wstatus, int options);

waitpid常用于等待任意的进程,关于参数:

  • pid:指定的进程,-1表示等待任意进程。
  • wstatus:输出型参数,获取子进程的退出结果(退出码和退出信号)
  • options选项:(常常设置为0表示阻塞等待,也可以设置为WNOHANG表示非阻塞等待)

获取退出信息

退出信息是一个16位的字段

0-7位表示终止信号,8位标识核心转储,9-15表示退出码

 演示获取退出信息

  1 #include<stdio.h>
  2 #include<sys/wait.h>
  3 #include<stdlib.h>
  4 #include<unistd.h>
  5 int main(){
  6     pid_t  rid=fork();
  7     if(rid==0){
  8         //子进程
  9         printf("我是子进程,我要退出了\n");
 10         exit(123);
 11     }
 12 
 13     //父进程等待回收
 14     int code=0;
 15     pid_t id=waitpid(-1,&code,0);
 16     //显示退出的信息
 17     printf("父进程等待成功,子进程的退出信息,exit_code:%d,sig:%d\n",  (code>>8)&0xFF,code&0x7F);
 18     return 0;
 19 }

通过信号将子进程终止,父进程也能读取到

但是这样退出需要程序员自己做位运算,比较麻烦,库函数提供宏,获取退出退出信息。

  • WIFEXITED:退出码
  • WEXITSTATUS:信号

 这里就不做演示了,用法比较简单。


父进程如何得知子进程退出信息

引出一个共识:硬件设备有它的等待队列,而PCB内也会内置等待队列。

所以这就是父进程调用wait阻塞的原因。


父进程等待多个子进程

如果没有保存frok之后的id,一般都是通过waitpid(-1)一次性等待。

非阻塞等待子进

通过waitpid的op选项字段,设置为非阻塞等待

如果rid>0等待成功,rid==0无进程回收,rid<0表示出错

程序替换

程序替换常用于父子进程分离、父进程调用其它语言、进程间的协作等。

见一见进程替换

调用exel函数,替换系统进程 ls


程序替换的原理

  • 替换进程的代码+数据(包括堆栈数据),替换后的新进程从main函数开始执行。
  • OS对页表的重新映射,保证新程序的代码+数据会被正确映射到物理内存上。
  • 原本子进程可能和父进程共享代码,现在会重新申请物理内存,存放新进程的代码。实现父子进程的分离。

程序替换的方法

必须找到程序的替换的可执行进程

指定替换的方法


认识程序替换函数

C语言为程序替换提供6个函数,以满足不同的场景需求。

实际上这些函数换汤不换药,用法基本一致。

 exec表示执行

  • l:list 参数以列表的方式传递(命令行上怎么写,这里就怎么写),比如"ls" "-a "  "-l"
  • p:指定可执行程序的文件名,会自动到PATH中寻找
  • v:对应的是l,利用 char * argv[ ]数组,将参数传递
  • e:是环境变量表

演示以数组参数


程序替换我们自己的进程

利用C语言调用C++

注意:

环境变量被子进程继承是默认的行为,为什么?
程序替换只替换代码+数据,不替换地址空间中的命令行参数和环境变量表。

 

当我们执行可执行程序的时候,OS为我们做的就是创建PCB,加载代码+数据。

而这个加载的操作就是程序替换。

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

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

相关文章

Qt 模型视图(四):代理类QAbstractItemDelegate

文章目录 Qt 模型视图(四):代理类QAbstractItemDelegate1.基本概念1.1.使用现有代理1.2.一个简单的代理 2.提供编辑器3.向模型提交数据4.更新编辑器的几何图形5.编辑提示 Qt 模型视图(四):代理类QAbstractItemDelegate ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方…

手写流程图元素检测系统源码分享

手写流程图元素检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

安装WINDOWS微软商店已下架的WSL系统,以UBUNTU 16.04 为例

下载WSL系统 方法1&#xff1a;POWERSHELL 用powershell下载 PowerShell Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile Ubuntu.appx -UseBasicParsing 1 如果下载时间很长&#xff0c;可以这样把进度条关闭&#xff1a; $ProgressPreference Silentl…

Vue特性

Vue概念 Soc原则&#xff1a;关注点分离原则 Vue 的核心库只关注视图层&#xff0c;方便与第三方库或既有项目整合 Model&#xff08;模型&#xff09;&#xff1a;表示应用程序的核心数据和业务逻辑。模型通常包含数据和与数据相关的操作。它独立于视图和视图模型&#xff…

Rust表达一下中秋祝福,群发问候!

一、Rust表达一下中秋祝福 在Rust中&#xff0c;表达中秋佳节的祝福可以通过定义一个包含祝福语的字符串变量&#xff0c;并使用标准输出函数来打印这个字符串。以下是一个简单的Rust程序示例&#xff0c;用于展示如何用Rust编写并打印中秋佳节的祝福语&#xff1a; fn main()…

3谐振功率放大器的实际电路设计

1原理电路 下图是谐振功率放大器的原理电路&#xff0c;如果我们照着下图搭一个电路&#xff0c;会发现它可能实现不了功率放大?这是为什么&#xff1f; 2实际电路设计 2.1要注意直流馈电线路 馈电原则(馈电供电)&#xff1a; 1&#xff09;保证直流电流分量流过直流电源&…

wordpress源码资源站整站打包32GB数据,含6.7W条资源数据

源码太大了&#xff0c;足足32gb&#xff0c;先分享给大家。新手建立资源站&#xff0c;直接用这个代码部署一下&#xff0c;数据就够用了。辅助简单做下seo&#xff0c;一个新站就OK了。 温馨提示&#xff1a;必须按照顺序安装 代码下载

【Linux】理解和解释shell命令的工具

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;C语言编程&…

阿德里安·欧拉博士Dr Adrian Euler

阿德里安欧拉博士 金融学副教授 https://apps.dur.ac.uk/biography/image/777 屬属 联系商学院金融学副教授 传 杜伦大学商学院金融学副教授&#xff08;教学&#xff09;阿德里安欧拉博士是一位金融理论家和实践家&#xff0c;在行业和高等教育实践方面拥有丰富的经验 - 教学、…

工程师 - PCI介绍

What Is Peripheral Component Interconnect (PCI)? 什么是外设组件互连&#xff08;PCI&#xff09;&#xff1f; PCI bus connects peripherals to the motherboard PCI 总线将外设与主板连接起来 By Mark Casey Updated on October 17, 2021 Reviewed by Ryan Perian 外…

web网站的任意文件上传下载漏洞解析

免责申明 本文仅是用于学习检测自己搭建的任意文件上传下载漏洞相关原理,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其所在国家地区相关法规内容【…

Python 的 WSGI 简单了解

从 flask 的 hello world 说起 直接讨论 WSGI&#xff0c;很多人可能没有概念&#xff0c;我们还是先从一个简单的 hello world 程序开始吧。 from flask import Flaskapp Flask(__name__)app.route("/", methods[GET]) def index():return "Hello world!&q…

完结马哥教育SRE课程--服务篇

文章目录 一、MySQL1.数据库范式2.SQL结构化查询语言3.存储引擎InnoDB和MyISAM4.索引Index5.事务6.日志管理7.MySQL备份和恢复8.MySQL主从复制9.MySQL高可用MHA 二、Redis1.NoSQL的特点2.Redis特性3.ROB和AOF4.Redis数据结构5.Redis主从复制6.Redis 哨兵机制7.Redis Cluster 三…

bpf的了解以及bpftrace的简单练习

最近接触到bpf的概念&#xff0c;简单做一些练习&#xff0c;做以下整理&#xff0c;学习笔记。 0&#xff1a;总结 使用ebpf可以实现的功能打开新世界&#xff0c;可以不改变源码的情况下&#xff0c;实现内存&#xff0c;网络&#xff0c;对应接口等各种期望内容的监控。 …

记忆化搜索(算法篇)

算法篇之记忆化搜索 记忆化搜索 概念&#xff1a; 记忆化搜索就是深度优先搜索的一种优化策略&#xff0c;记忆化搜索深度优先搜索形式动态规划思想由于dfs本质是暴力搜索&#xff0c;没有很好地处理重叠子问题&#xff0c;因此很低效记忆化算法在求解地时候还是按照自顶向下…

固态硬盘数据怎么恢复?用这4个软件你就知道了。

其实想要恢复固态硬盘里面的数据&#xff0c;方法有很多种。我们可以从回收站恢复&#xff0c;用备份恢复&#xff0c;或者是找专业人员帮助恢复。如果这些方法都不行的话&#xff0c;可以试试使用专业的数据恢复软件。我知道的数据恢复软件就有好几款&#xff0c;可以分享给大…

java编程行业特点

Java编程行业是一个庞大且充满活力的领域&#xff0c;它涵盖了从桌面应用到企业级应用、从Web开发到移动应用、从大数据处理到云计算服务的广泛范围。Java作为一种跨平台、面向对象的编程语言&#xff0c;自1995年发布以来&#xff0c;一直受到全球开发者的青睐&#xff0c;并在…

我的5周年创作纪念日,不忘初心,方得始终。

一、机缘 五年前&#xff0c;我怀着对知识的渴望和分享的热情&#xff0c;踏入了 CSDN 这个充满活力的技术交流平台&#xff0c;开启了我的创作之旅。那时的我&#xff0c;刚刚在技术的海洋中启航&#xff0c;渴望找到一个地方记录自己的成长足迹&#xff0c;与更多的人分享自…

【模板的特殊继承关系】用参数化的方式表达成员函数的虚拟性

一、使用混入技术实现的简单范例 成员函数的虚拟性可以通过特殊的继承来表达&#xff0c;我们先看看一个简单的范例&#xff0c;通过混入技术来实现&#xff1a; //基类 template<typename... T> class Base:public T... { public:void myfunc(){std::cout << &q…

禹神3小时快速上手typescript

一、TypeScript简介 TypeScript 由微软开发&#xff0c;是基于 JavaScript 的⼀个扩展语⾔。TypeScript 包含了 JavaScript 的所有内容&#xff0c;即&#xff1a; TypeScript 是 JavaScrip t 的超集。TypeScript 增加了&#xff1a;静态类型检查、接⼝、 泛型等很多现代开发特…