Linux——进程的等待

news2024/10/3 16:48:43

目录

  前言:

一.进程等待

父进程回收子进程信息的相关函数1:wait函数

        实验案例1:设置wait函数参数为NULL

        实验案例2:wait函数带wstatus参数的案例:当子进程正常运行完退出时

        情况3: wait函数带wstatus参数的案例:当子进程执行异常导致的终止时

  总结:

父进程回收子进程的相关函数2:waitpid();

           其中参数2status是重点要学习的!

           例1:使用waitpid函数——子进程运行途中出现异常错误的情况:

           例2:修改部分例1中子进程的代码:子进程运行途中运行正确,但结果不正确:

           阻塞等待VS 非阻塞等待:

二.总结:进程等待的必要性


  前言:

        一说到进程等待,就不得不提到僵尸进程了,有关僵尸进程,不了解的友友们可以看这篇快速了解一下什么是僵尸进程:Linux下的进程状态和 僵尸/孤儿进程的区别 _   中的Z状态


        在 Unix/Linux 系统中,正常情况下,子进程是通过父进程创建的,且两者的运行是相互独立的,父进程永远无法预测子进程到底什么时候结束。当子进程调用 exit 命令结束自己的生命时,其实它并没有真正的被销毁,内核只是释放了该进程的所有资源,包括打开的文件、占用的内存等,但是留下一个称为Z状态的数据结构,这个结构保留了一定的信息 (包括进程号 the process ID,退出状态、运行时间),这些信息直到父进程通过使用特定的系统调用函数获回收子进程的退出信息资源后,子进程才会被真正释放。这样设计的目的主要是保证只要父进程想知道子进程结束时的退出信息,主动进行回收子进程信息,就可以避免Z状态的进程。

一.进程等待

编译运行:

杀掉子进程后,代码运行结果:

 

通过while循环和ps ajx指令实时观察当前进程正在运行的结果: 


父进程回收子进程信息的相关函数1:wait函数

函数功能:

        父进程一旦调用wait函数就立即阻塞自己,即父进程立刻终止自己当前执行的一切指令,先对子进程的退出资源进行回收!由wait函数分析是否当前进程的某个进程已经退出,如果让它找到了这样一个已经变成zombie状态的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果wait函数没有找到,它就一直阻塞等待,直至找到一个结束的子进程或接收到了一个指定的信号为止,那么父进程的执行流也得一直跟着wait等待,wait什么时候找到僵尸状态的子进程返回给父进程,父进程什么时候才会继续执行自己的执行流!

 

        wstatus的作用就是用于保存子进程的状态信息,有了wstatus,父进程就可以了解子进程退出的原因,是正常退出还是有啥错误导致的退出!!!很重要! 

实验案例1:设置wait函数参数为NULL

进程状态检测器: 

篮框中表示:这段是父子进程正常运行的状态信息。

橙色框表示:这段是子进程退出后,父进程仍在运行的状态信息此时,pro_wait.exe进程退出,变为僵尸状态,等待着父进程的回收。

绿色框表示:这段就是子进程退出后,父进程采用wait函数“回收了子进程的资源”,父进程继续正常运行,此时子进程从僵尸状态-->死亡状态,真正被释放。


例1实行的方案图:


 实验案例2:wait函数带wstatus参数的案例:当子进程正常运行完退出时

知识点讲解:        

        WEXITSTATUS(status) :当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值。

        如果子进程调用exit(5) 退出,WEXITSTATUS(status)就会返回5;                                            如果子进程调用exit(7)WEXITSTATUS(status)就会返回7。

运行结果:


情况3: wait函数带wstatus参数的案例:当子进程执行异常导致的终止时

 

运行结果:

 

总结:

    非正常结束==异常结束 :

                WIFEXITED(status)==1时        等价于    WIFSIGNALED(status)==0时的情况

     非异常结束==正常结束:

                 WIFSIGNALED(status)==1时   等价于    WIFEXITED(status)==0时的情况 


 父进程回收子进程的相关函数2:waitpid();

        说完了wait0,我们再来说说waitpid(),可以说,waitpid是wait的升级版,具体我们看下面:

函数原型: pid t waitpid(pid t pid ,int *status , int options);

可见,waitpid相比于wait多了两个参数,下面具体来说一下这两个参数的用法。

参数1:

 参数2:

status:与wait的wstatus用法一样都是WIFE....· WIFS。
status详细说明:
        用于保存出发wait的信号status值或者退出时exit (code)中的code值。
        这个参数将保存子进程的状态信息,有了status,父进程可以了解子进程为什么会退出,它是正常退出还是异常退出。

参数3:

options :(常用的有两个)

  1.         0是默认行为,表示阻塞等待:进程要等待资源而得不到推进时,产生阻塞时等待(大部分的接口是阻塞的)
  2.         WNOHANG:如果没有子进程退出,立即返回,不会阻塞进程;如果结束了,则返回该子进程的进程号(return immediately if no child hasexited.)——表示为非阻塞时等待 (非阻塞式调用 )

     

        如果父进程在调用waitpid( 函数时,当指定等待的子进程已经停止运行或结束了,则waitpid() 会立即返回;但是如果子进程还没有停止运行或结束,则调用waitpid()函数的父进程则会被阻塞,暂停运行


其中参数2status是重点要学习的!

        wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
        如果传递NULL,表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图 (只研究status低16比特位) : 

 

        status 整型(一个整型无法表示多种退出状态),但整型有32个比特位,将其一分为二,高16位我们不必关心,低16位再一分为二,就变成了低七位和次低八位 (0-7位表示是否正常终止,8-15位为退出码) ,中间还有一位是core dump,这个不用管,没啥学的意义。

        status & 0x7F代表进程终止信号 ;(status >>8) & 0xFF代表进程退出码


        进程退出状态有三种:

1.运行结果完且正确、

2.运行完但结果不正确、

3.异常。

        进程结果是否正确由退出码决定,但异常情况下退出码无用,不过异常时会返回导致异常的信号编号。所以如果进程始终没有返回信号编号,则其退出非异常(正常退出)。 

        总结:

        所以说:进程运行成功,但结果的是否正确就只需要看:(status>>8) & 0xFF——status次低8位的值;

        进程运行途中,出现了各种错误(除零错误、段错误....),只需要看:status&0x7F——status低7位的值。

例1:使用waitpid函数——子进程运行途中出现异常错误的情况:

使用了错误语句——被动终止退出:

 

编译运行: 

        运行结果:因为代码中出现了除零错误,子进程会收到8号信号——SIGFPE(浮点运算错误信号),提前被终止运行。

 

例2:修改部分例1中子进程的代码:子进程运行途中运行正确,但结果不正确:

使用了exit函数,主动退出:

结果运行: 

 

 


接下来讲一讲waitpid函数中第三个参数option

上面说过option参数有两种选择,分别是阻塞式等待和非阻塞式等待:

阻塞等待VS 非阻塞等待:


        其一是0,0是option的默认选项,它代表着阻塞等待,即父进程会先一直等待子进程退出后才进行回收资源;
    

       阴塞等待的案例:比如张三想要叫李四请教问题,于是周未请他吃饭,张三去了李四楼下,然后打电话叫他,李四这时候正在忙着看书,电话中,张三说:“现在我请你去吃饭,你有时间没?  李四说:“我正在看书,你需要等10分钟。”,张三回说:“好的”,但是张三电话没挂,他俩一直在通话中,而张三一直在楼下等他。直到10分钟后,李四在电话中说了一句:“好了,可以了,我正在下楼”,张三看到李四下了楼,高兴的和他去吃饭了。

        

        在上面这个案例中,张三和李四一直处于通话中,张三一直在等李四下楼吃饭,没有干其他的事情,很专一!


        二是WNOHANG,它代表非阻塞等待,即父进程每隔一段时间就对子进程进行状态检测,会有次的状态检测-称为轮询。轮询过程中父进程不会把全部精力都投入到子进程中,它可以在等待的过程中,干些其他的事情!

       非阻塞等待的案例:张三还是想请教李四问题,还是周末请他吃饭,张三去了李四楼下,打电话叫他,李四这时候正在收拾家务,电话中张三说:“今天再一块吃个饭把,有些问题要请教你。”,李四说:“等我收拾完家务,你需要等会”,张三说:“好的”,基于上次漫长的等待,张三这次提前挂断了电话,刷起了抖音,在微信和朋友聊起了天,几分钟后,张三又打了个电话,问李四好了没,李四说仍在收拾:几分钟后,张三又做了同样的事,李四仍在忙;在这十几分钟中,张三给李四打了好几个电话,都在询问李四好了没。最后过了5分钟,李四下了楼,张三终于和李四去吃了饭。

        

        在这个案例中,张三经常打电话询问李四状态,这就是“轮询”,但相比第一次,张三没有一直和李四处于通话中,张三在等待过程中干着自己的事情。


        阻塞等待和非阳塞等待都有各自的好处,非阻塞是复杂一些,但父进程可以忙于处理其他进程,阻塞等待是简单但需要一直等该子进程处理完自己的事情才行。 

 


总结:进程等待的必要性


1、子进程退出,父进程如果不管不顾,就可能成“僵尸进程’的问题,进而造成内存泄漏。

2、进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。


3、父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。


4、父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。

 

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

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

相关文章

Softing“物联网连接和OPC UA通信”系列研讨会

— 免费线上研讨会概览 — 您是否正在为车间应用寻找机器连接?您是否需要为创新的物联网解决方案制定架构决策?或者您是否已经选择了物联网平台,需要连接组件来访问自动化网络中的数据?在Softing线上研讨会中,我们将讨…

JavaScript 进阶 (三)

目录 编程思想 面向过程编程 面向对象编程 构造函数 原型 原型 constructor 属性 对象原型 原型继承 原型链 编程思想 面向过程编程 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次 调用…

Python中的封装、继承与多态

1. 前言 面向对象的三大特性,想必大家肯定是耳熟能详。就是今天要介绍的内容:封装、继承、多态。面向对象的思想都是一样的,这里我用Python进行实现! 2. 封装 2.1 什么是封装呢? 封装就是:我写了一个类…

【T6/T3】根据畅捷通T6/T3账套备份文件判断软件的版本

【问题需求】 当畅捷通T6/T3软件只有正常的账套备份文件的时候, 通过账套备份文件判断软件版本, 进而安装软件恢复数据。 【解决方法】 【畅捷通T6】 找到T6的备份文件, 用记事本打开【UfErpAct.lst】文件。 查看【VersionbatchflagForUFDAT…

【linux】web基础与HTTP协议

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 web基础与HTTP协议 一、DNS/HTML1.域名的概述2.域名注册3.网页的概念4.HTML概述5.网页基本标签 二、web基础1.web概述2.静态网页3.静态网页特点4.动态网页5.动态网页的特点 三…

软件开发SOLID设计原则

前言:SOLID设计原则,不管是软件系统还是代码的实现,遵循SOLID设计原则,都能够有效的提高系统的灵活和可靠性,应对代码实现的需求变化也能更好的扩展和维护。因此提出了五大原则——SOLID。 我是通过老师讲解以及老师…

【深入浅出Spring Security(三)】默认登录认证的实现原理

Spring Security 默认登录认证的实现原理 一、默认配置登录认证过程二、流程分析登录页面的由来表单登录认证过程(源码分析) 三、UserDetailsServiceSpring Security 中 UserDetailsService 的实现默认的 UserDetailsService 配置(源码分析&a…

【送书福利-第七期】《分布式中间件核心原理与RocketMQ最佳实践》

大家好,我是洲洲,欢迎关注,一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢迎大家在CSDN后台私信我! 本文目录 一、前言二、内容介绍三、作者介…

孪生诱捕网络在欺骗防御领域的应用

随着以数字化、网络化和智能化为特征的信息化浪潮的蓬勃兴起,信息已经成为重要的战略资源与重要生产要素,在国家的发展和人们的生产生活中起到至关重要的作用。信息化在给人们带来便利的同时,网络信息安全问题也日益凸显。经过多年的网络安全…

【Linux】Linux 文件系统与设备文件

Ref: 《Linux设备驱动开发详解:基于最新的Linux4.0内核》中的第5章《Linux 文件系统与设备文件》 基于Linux 5.10 本文结合源码和实例分析了Linux 文件系统与设备文件,主要介绍文件系统的构成和发展,以及三种虚拟文件系统debugfs procfs sysf…

《微服务实战》 第二十七章 CAS

前言 本章节介绍CAS 1、CAS的概念 CAS的全称为:CompareAndSwap,直译为对比和交换。 CAS实际是普遍处理器都支持的一条指令,这条指令通过判断当前内存值V、旧的预期值A、即将更新的值B是否相等来对比并设置新值,从而实现变量的原子性。 Syn…

二进制安装Kubernetes(K8s)集群---从零安装教程(带证书)

一、实验环境 1、安装说明 selinux iptables off 官方网站:https://kubernetes.io/zh-cn/docs/home 主机名IP系统版本安装服务master0110.10.10.21rhel7.5nginx、etcd、api-server、scheduler、controller-manager、kubelet、proxymaster0210.10.10.22rhel7.5nginx、…

【细读Spring Boot源码】Spring如何获取一个Bean?BeanFactory的getBean方法

前言 在读refresh(context);时,finishBeanFactoryInitialization(beanFactory);中beanFactory.preInstantiateSingletons();用于实例化剩余所有的non-lazy-init的单例。这里包含了前置处理器和后置处理器 这里面就用到了本文主题getBean(beanName); 下面具体看看这…

4.数据结构期末复习之树

1.树的概念(一对多)(要求会写遍历序列) 1)n>个节点,n0时为空树2)仅有一个根节点3)左右节点互不相交,子节点一对多2.树的特点 1.子树之间没有关系 2.节点不属于多个子树(一个节点只能在一颗子树里面)3.没有回路(就是成环)4.有层次性3.术语 1.节点的度:拥有子树的个数…

ArcGIS教程——ArcGIS快速入门

实例数据:https://pan.baidu.com/s/184wwCmWrJdb-qjxsT614EQ 密码:dowv ArcGIS for Desktop是一套完整的专业GIS应用程序,包含有ArcMap、ArcCatalog、ArcToolbox、ArcScense、ArcGlobe和Model Builder等。其中ArcMap、ArcCatalog、ArcToolbo…

Unreal Niagara粒子入门3 - 根据模型顶点发射粒子

在一些游戏中经常会出现根据模型顶点位置发射粒子的情况,这次就来实现一下该效果: 1.基础创建操作 首先从空粒子发射器开始创建,右键NiagaraSystem->Create empty system,打开粒子系统后再右键Add empty emitter&#xff1a…

【智能软件安全】上海道宁为您带来智能软件安全平台——​Veracode,帮助您全面地保护您构建和管理地应用程序

Veracode可以全面地 保护您构建和管理地应用程序 在现代软件 开发生命周期的 每个阶段不断发现并修复缺陷 Veracode通过 建立一种在安全和开发团队之间 架起桥梁并授权 开发人员成为 安全倡导者的积极文化 从一开始就防止常见的安全漏洞 开发商介绍 Veracode成立于20…

腾讯云8核16G服务器18M带宽CPU性能可支撑多少人同时在线?

腾讯云8核16G轻量服务器CPU性能如何?18M带宽支持多少人在线?轻量应用服务器具有100%CPU性能,18M带宽下载速度2304KB/秒,折合2.25M/s,系统盘为270GB SSD盘,月流量3500GB,折合每天116.6GB流量&…

【CocosCreator入门】CocosCreator组件 | TiledMap(地图)组件

Cocos Creator是一款流行的游戏开发引擎,具有丰富的组件和工具,其中TiledMap组件可以帮助开发者快速创建、加载和渲染地图。 目录 一、组件介绍 二、组件属性 三、脚本控制 3.1加载地图 3.2渲染地图 四、详细说明 五、关闭裁剪 六、节点遮挡 一、…

Linux中与进程间通信相关的内核数据结构

【摘要】本文详细讲述了Linux内核中与进程间通信概念相关的内核数据结构及其内在联系。 九、进程间通信(IPC)相关数据结构 9.1 ipc_namespace 从内核版本2.6.19开始,IPC机制已经能够意识到命名空间的存在,但管理IPC命名空间比较简单,因为它…