linux进程控制——进程等待——wait、waitpid
前言:本节内容仍然是进程的控制,上一节博主讲解的是进程控制里面的进程创建、进程退出、终止。本节内容将讲到进程的等待——等待是为了能够将子进程的资源回收,是父进程等待子进程。 我们前面的章节也提到过等待, 那里的等待是进程等待硬件设备, 而这里是进程等待软件设备,也就是说——进程等待可以发生在硬件上面, 也可以发生在软件上面。 另外, 通过本节的学习, 友友们可以理解一个完整的进程控制是什么样的, 是怎么样的流程。
ps:本节内容适合学习了进程创建、退出与终止的友友们观看
为什么要有进程等待
进程等待, 对于一个子进程来说, 如果子进程退出, 父进程不管不顾, 就可能造成僵尸进程的问题。 进而造成内存泄漏!!!
进程等待的一个原因就是为了子进程能够在僵尸进程的时候被父进程回收, 防止内存泄漏。 ——僵尸进程无法被杀死,需要父进程等待来杀掉它, 从而解决内存泄漏问题。
第二个原因就是我们要通过进程等待获取子进程的退出情况。——知道我布置给子进程的任务, 它完成的怎么样了? ——要么关心, 要么不关心这个是可以选择的。
进程的等待是什么?
进程等待就是通过系统调用, wait/waitpid, 来进行对子进程进行状态检测与回收的功能!
进程等待是怎么实现的?
进程等待是如何实现的用一句话来说就是——父进程通过调用wait/waitpid进行僵尸进程的回收问题!
但是, 这里就有问题, wait接口和waitpid接口是什么? 这就是我们本篇文章着重讲解的知识点。 现在我们先来看一下man手册:

wait是一个系统调用接口, 包含在sys/types.h头文件里。 定义就可以见上图, 然后里面的status参数暂时可以不考虑。
wait和waitpid的作用就是等待一个进程, 当这个进程退出后, 那么父进程就可以等待子进程
, 回收子进程的资源。
wait和waitpid的返回值
返回值如果是大于零的, 那么就是等待成功, 并且是被等待的子进程的pid。
单进程等待
下面是实验(使用wait, waitpid和wait一样, 不用着急, waitpid后续会讲解)

上面的代码就是先创建一个子进程, 然后子进程5s后变成僵尸进程被等待, 父进程10后运行等待, 然后关闭子进程。 但是这个程序很难观察到wait的作用,我们修改一下:

将上图板块中的代码改成图中所示的样子。 然后运行程序, 我们就可以观察到:



多进程等待
上面是单进程的情况, 那么多个子进程的时候, wait等待的是哪一个进程呢? ——wait一次是等待一个进程, 是随机的。 而且只等待一个进程, 那么现在我们来试验一下,下面是代码:

我们运行后, 可以观察到, 5s后, 最后一个创建的子进程都已经是僵尸进程了。

然后随即等待, 全部等待成功后我们就会发现, 进程被回收了。

阻塞等待
那么我们现在思考一下, 当子进程没有变成僵尸, 一直在运行的时候, 父进程等待还有用吗?
现在看下面一个实验, 这里面创建了一个子进程, 这个子进程会无限次循环下去, 但是父进程会在10s后进入等待, 观察现象:

运行结果如下,可以发现, 其实子进程没有进入僵尸, 那么父进程的等待对不它不起效果。——这个其实就是父进程在wait这里发生了阻塞等待!!也就是说, 父进程不会退出, 一直等待子进程的返回。

那么, 什么是阻塞等待——阻塞等待就是子进程不退出, 父进程默认在wait的时候, 也就是调用这个系统调用的时候, 不发生返回, 这个就叫做阻塞等待。
知道了阻塞等待之后, 我们也知道, 任何进程都会变成僵尸进程, 然后被进程等待回收资源, 等待是必须的。 僵尸进程是必须的。——知道了这些, 我们就可以想到一个完整的进程控制代码就是:有创建(fork), 有终止(exit), 有等待(wait)。
waitpid
现在我们来说一下waitpid。 waitpid的功能多于wait, wait是waitpid的子集。

waitpid的第一个参数是等待的进程的pid(也就是说可以指定等待对象), 也可以传送-1, 表示随即等待和wait一样。 并且waitpid的返回值是等待的进程的pid。
退出信息:
退出信息是通过第二个参数, status获取到。 ——wait里面是第一个参数。
对于status, 这个动能可以使用可以不使用——也就是说可以传参, 也可以不传参。 status是一个指针, 意思是说将函数内部的数据通过status带出来, 也就是输出型参数。
并且这个int是被当做及部分使用的。 ——因为int有32给比特位, 其中八个或者十六个比特位表示一个东西, 另外又表示一个东西, 这里我们进行试验一下:
首先我们要写或者退出结果必须顶一个整数变量, 然后取地址变量传给waitpid, 调用系统嗲用后获取相应的结果, 再带出这个结果, 然后status就会发生变化。
运行结果如下:

这里之所以退出2816, 就要考虑几个问题:
我们知道, 进程推出的时候, 主要有三种场景——退出结果正确, 推出结果不正确, 异常。 那么, 子进程退出, 父进程希望获取什么信息呢?
首先:1、子进程代码是否异常?——不同信号表示不同异常
2、没有异常, 结果对吗? exitcode, 不对是因为什么呢? ——不同退出码表示不同原因
那么, status最少能够获取这个进程是否发生了异常, 异常原因, 结果是否正确? 为什么?——这些信息都保存在了status的低16比特位, 并且这里我们只谈status的低16位。

这里的低7位就是代表进程的终止信号, 如果进程异常退出, 这里会保存下来什么异常——比如除零错误, kill -9等等。
这里的第八位是core dam标志——这个暂时不谈。
前八位就是代表正常退出的状态。
而我们的子进程上面是可以看到是正常退出——信号位0; 并且退出码为11, 二进制就是1011, 然后合起来就是0000 1011 0000 0000——这个二进制转化为十进制就是2816.
现在我们来谈一下信号:

我们就会发现, 这些信号里面没有0号信号——没有零号信号, 那么这个时候我们是不是就可以通过这个进程是否是零号信号, 来判断是否发生了异常?
一旦进程发生异常, 那么不同信号就会代表不同的异常, status就会待会不同的结果。
现在, 我们来考虑——父进程要拿到子进程状态数据, 为什么要调用wait等待系统调用呢? 直接用全局变量不行码?——答案是不可以, 我们知道, 父子进程是独立的, 如果在子进程里修改了这个全局变量, 本质上就是发生了写时拷贝, 父进程里面的全局变量并不会被修改。 所以不可以。
现在我们想要将子进程的状态分开打印——打印信号和退出码, 怎么打印呢?
下面是一个代码:
程序和上面一样, 但是打印的内容:

那么我们给一个除零错误, 就会看到:

我们使用kill -9就可以看到:

非阻塞轮询
以上就是本节的全部内容, 下面是本节笔记:




相关文章:
linux进程控制——进程等待——wait、waitpid
前言:本节内容仍然是进程的控制,上一节博主讲解的是进程控制里面的进程创建、进程退出、终止。本节内容将讲到进程的等待——等待是为了能够将子进程的资源回收,是父进程等待子进程。 我们前面的章节也提到过等待, 那里的等待是进…...
Shell脚本的进程管理
进程管理是系统管理的重要方面,通过对进程的监控、启动、停止和重启,可以保证系统的稳定运行。Shell脚本是一种强大的工具,可以对进程进行自动化管理,提高效率和准确性。 参考:shell脚本进程管理 - CSDN文库 shell脚本…...
JLink烧录失败
1. 现象: 这个位置是灰色的,没有SW Device信息。 MDK下面的打印: J-Flash的打印: windows上面的弹框的现象没有截屏。 2. 解决办法: 1.打开J-Link Commander,输入unlock kinetis,看现象不起作用,网…...
Monorepo简介
Monorepo 第一章:与Monorepo的邂逅第二章:Multirepo的困境第三章:Monorepo的魔力 - 不可思议的解决问题能力第四章:Monorepo的挑战与应对策略第五章:总结第六章:参考 第一章:与Monorepo的邂逅 …...
SpringBoot打包为jar包,打包前注意事项及打包教程
在打包 Spring Boot 项目为 JAR 包之前,有一些重要的注意事项和步骤,以确保打包过程顺利并生成一个可正常运行的 JAR 包: 1. 检查依赖和版本 确保所有依赖项和插件版本是最新且兼容的,特别是 Spring Boot 版本和其相关依赖的版本…...
B端系统UI个性化设计:感受定制之美
B端系统UI个性化设计:感受定制之美 引言 艾斯视觉作为ui设计和前端开发从业者,其观点始终认为:在当今竞争激烈的商业环境中,B端(Business-to-Business)系统的设计不再仅仅是功能性的堆砌,而是…...
前端常用 utils 工具封装
// 函数防抖 export function debounce(fn, interval) {let timerreturn function (this, ...args) {clearTimeout(timer)const context thislet params [...args]timer setTimeout(() > {fn.call(context, ...params)}, interval || 1000)} }// 函数节流 export functio…...
项目都做完了,领导要求国际化????--JAVA后端篇
springboot项目国际化相信各位小伙伴都会,很简单,但是怎么项目都做完了,领导却要求国际化文件就很头疼了 国际化的SpringBoot代码: 第一步:创建工具类 /*** 获取i18n资源文件** author bims*/ public class Message…...
国内备受好评PostgreSQL数据库性能如何?
为什么国内很多数据库采用PostgreSQL数据库作为基础,再次开发自己的产品呢?不仅仅是因为PostgreSQL数据库开源免费、PostgreSQL 数据库的性能也是相当出色的,具有以下几个方面的特点: 1. 处理大规模数据: - 能够有效地管理和处…...
彻底搞懂前端跨域解决方案
一、浏览器的同源策略 1、同源策略概述 同源策略是浏览器为确保资料安全,而遵循的一种策略,该策略对访问资源进行了一些限制。 2、什么是源(origin)? 3、示例 4、同源请求 5、非同源请求 二、跨域会受到哪些限制 1…...
Kafka基础概念
MQ消息中间件 1)总览: 消息中间件 这里我们主要学习的是kafka的基础概念 具体参考黑马头条:https://www.bilibili.com/video/BV1Qs4y1v7x4/?spm_id_from333.337.search-card.all.click 2)消息中间件对比 3)Kafka介…...
【论文阅读笔记】DeepCAD: A Deep Generative Network for Computer-Aided Design Models
1 引言 现有3D生成模型: 3D点云:大量离散的3D点组成的数据表示形式; 多边形网格:一系列相连的多边形组成的3D模型; 水平集场:使用数值函数来表示物体的边界,并根据函数值的正负来确定物体内部…...
《如鸢》开通官号,女性向游戏爆款预定
今天,备受瞩目的沉浸式剧情卡牌手游《如鸢》正式开通了官方社媒账号并发布了玩家信。 《如鸢》由灵犀互娱倾力打造,游戏不仅拥有跌宕起伏的权谋剧情,更采用Live2D技术,为玩家带来沉浸式的游戏体验,吸引了众多玩家关注。…...
OpenAI再下一城:发布Voice Engine,可使用文本和参考语音合成说话者的新语音!
转自 机器学习算法工程师 OpenAI又发布了一个最新的工作:Voice Engine。Voice Engine可以使用文本输入和单个 15 秒音频样本生成听起来自然且与原始说话者非常相似的语音。而且,一个小型模型仅通过一个 15 秒的样本就能创造出富有情感且逼真的语音。Voi…...
KVM高级功能部署
一、概述 KVM(Kernel-based Virtual Machine)是一种基于内核的虚拟化技术,它依赖于CPU的虚拟化扩展(如Intel VT和AMD-V)来实现虚拟机的创建、管理和调度。KVM虚拟化技术因其高效、稳定的特点,在云计算和企…...
【C语言】柔性数组(打开前所未见的大门)
文章目录 前言柔性数组1.1 概念1.2 柔性数组的特点1.3 柔性数组的使用1.4 柔性数组的优势 总结 前言 说到柔性数组,相信有很多学过C语言的读者都不知道这是个什么东西。不过没有关系,相信本章能够带你从到认识到掌握柔性数组,做一个充满知识…...
设计模式17-适配模式
设计模式17-适配模式 动机定义与结构C代码推导总结应用具体应用示例 动机 在软件系统中由于应用环境的变化常常需要将一些现存的对象。放到新的环境中去应用。但是新环境要求的接口是这些现存对象所不满足的。那么这种情况下如何应对这种迁移的变化?如何既能利用现…...
react ant Input defaultValue={value}设置了value值以后,但是defalult没有赋值上,输入框也没有显示
在 React 中,defaultValue 是一个非受控属性,而 value 是一个受控属性。这两个属性都可以用于设置 Input 组件的值,但是它们的工作方式有所不同。 value:这是一个受控属性,意味着输入框的值由 React 状态控制。每当状态…...
大模型开发如何把一段文字变成一组token?
在大模型开发中,将一段文字变成一组token通常称为"tokenization"(分词)。这是自然语言处理中的一个关键步骤,主要是将连续的文本划分成离散的单元(token),这些单元可以是单词、子词或…...
【MSYS】Windows Terminal 集成
Windows Terminal 集成 MSYS2安装在默认位置C:\msys64打开Windows Terminal打开JSON配置文件文件。 添加如下配置: "profiles": {"defaults": {},"list": [{"guid": "{71160544-14d8-4194-af25-d05feeac7233}"…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
