当前位置: 首页 > article >正文

linux下的进程等待(wait、waitpid)

目录

引言

进程等待的必要性

见见猪跑:是什么

怎么办

多个子进程时

阻塞等待

非阻塞轮询

参数一:

参数二

进程等待的原理

进程退出相关的宏

第三个参数option(设置等待的方式)


引言

在Linux操作系统中,进程控制是核心功能之一。进程的创建、执行、终止以及资源管理都是操作系统管理任务的重要组成部分。特别是在多进程编程中,进程间的同步和资源回收显得尤为重要。本文将重点介绍Linux系统中进程等待的机制,特别是waitwaitpid这两个系统调用。

进程等待的必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。
最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。
因此,为了获取这些信息,进程等待是必要的!
我们将通过进程等待是什么、为什么两步去完成讲解。

见见猪跑:是什么

先建立一个多进程的程序,观察现象。

perror:将错误码转化成错误码描述

如果打开文件错误,perror("file:"),那么打印结果是file: No such file or directory 

现象

子进程跑完循环之后退出,父进程一直执行。

发现子进程变成了僵尸,状态是Z,后面还跟着defunct备注。

怎么办

处理:wait等待子进程使之从z变成x

头文件在sys/types.h和sys/wait.h

等待成功之后返回pid,等待失败返回-1。子进程未结束返回0(wait默认情况下是阻塞等待)。

wait需要传入一个指针参数(后续讲解)

现象:

子进程由S----Z----正确退出释放。

多个子进程时

创建时,子进程执行结束接着退出,所以父进程执行继续循环,会创建多个子进程。

fork success是父进程的输出,可以看到,父子进程并不是有严格的执行规律

后去全部可以等待成功。

wait等待是一种泛型等待,只要你是父进程的子进程,那么wait就可以去等待。

阻塞等待

如果wait等待的子进程都不结束,那么父进程会一直停留在wait处等待子进程。

因此进程阻塞不只是进程在等待硬件资源的响应,在等待软件资源的响应时,也会造成阻塞!

非阻塞轮询

为了让父进程“有活干”,就不能让父进程一直阻塞在wait处。waitpid()接口可以实现非阻塞轮询。

返回值:
当正常返回的时候 waitpid 返回收集到的子进程的进程 ID
如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0
如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;
注意
waitpid(-1, nullptr,  0)等价于wait,进行泛型等待,并且是阻塞等待的方式(除非第三个参数设置为WNOHANG)
也可以等待成功

参数一:

直接传入子进程的pid(限制了等待对象)

参数二

这是一个输出型参数。获取进程的信息是通过status参数获取的

这两个接口的status含义一致

可以观察到status是256,并不是我们所“期待的 1”。

原因

进程的退出状态有三种

代码运行完毕,结果正确(0)
代码运行完毕,结果不正确(其他数字)                //这两种都是正常退出
代码异常终止(存在信号)
因此status必须表示这三个信息才能代表进程的退出状态。
对此status应该“分段”看待

当进程异常终止时(没执行完毕 )0-7bit为代表终止信号(signal信号)

信号最大为62,2^6所以用7个bite位表示(低七位

第八位:这是一个core dump标志,暂时不关心

次低八位:表示退出状态(退出码)

获得信息

exit signal(退出信号):status & 0x7F    (7F是0111 1111,按位与可得到低七位信息)

exit code(退出码) : (status >> 8 )& 0xFF         (FF是1111 1111 ,按位与 可得到次低八位信息)

不可以建立一个全局变量去获得相关的信息(写时拷贝、进程的独立性)

进程等待的原理

父进程获取子进程的内核pcb,并且将z状态改为x状态(在x状态下进行资源的释放)

为什么不直接去内核数据结构访问呢?父进程必须通过接口去访问子进程的pcb信息,OS不相信任何人

什么时候进程等待失败(不返回pid,返回-1)?只需要让第一个参数pid 随意 加减一个数字,让父子进程不匹配即可。(父进程只能回收自己的子进程)

进程退出相关的宏

WIFEXITED:检测子进程正常退出,返回非零值,否则返回0(wait if exited) 

WEXITSTATUS :正常退出时,获取退出码(wait exit status)

注意:前两个宏都得是退出的前两种状况:进程正常退出,而不是被信号所杀。

第三个参数option(设置等待的方式)

这就是我们所提及的非阻塞轮询。

如果第三个参数是0,那么仍然是阻塞轮询。

0:阻塞等待方式

用0的方式本身就会让父进程去等待子进程,让自己进入阻塞状态。

如果第三个参数设置为WNOHANG(wait no hang禁止等待),那么将不会停留在waitpid处。

非阻塞轮询由:非阻塞  +  循环构成

非阻塞ret有三种返回方式(都是立即返回,不会阻塞): 1.pid等待成功返回pid(跳出循环) 2.等待失败返回 -1 (跳出循环) 3.子进程还在运行返回0

阻塞等待

阻塞等待是指父进程在调用wait()或waitpid()函数时,如果没有子进程退出,父进程会暂停执行,直到有子进程退出。这是最常见的等待方式,适用于大多数IO类函数。在阻塞等待期间,父进程处于等待状态,无法执行其他任务。

非阻塞轮询

非阻塞等待是指父进程在调用waitpid()函数时,通过设置WNOHANG选项,即使子进程没有退出,父进程也不会暂停执行,而是立即返回继续执行其他任务。这种方式允许父进程在等待子进程的同时,执行其他操作,从而提高了程序的效率。

无论是阻塞等待还是非阻塞等待,父进程都是最后结束,因为父进程需要等待回收子进程(否则变成孤儿进程)。


http://www.kler.cn/news/365854.html

相关文章:

  • 大一物联网要不要转专业,转不了该怎么办?
  • kubeadm快速自动化部署k8s集群
  • 案例分析-嵌入式系统
  • mac电脑设置chrome浏览器语言切换为日语英语等不生效问题
  • YOLOv11改进策略【卷积层】| ECCV-2024 小波卷积WTConv 增大感受野,降低参数量计算量,独家创新助力涨点
  • 服务器与普通电脑的六大区别
  • Vue 3项目的性能监测和优化
  • 日常记录:es TransportClient添加证书处理
  • vscode 配置构建、调试QT项目
  • uniapp renderjs页面传值
  • 【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (七):MongoDB的设置
  • 虚拟化基础
  • java List<Map<String, Object>> 转 List<JSONObject> 的几种方式
  • Log4j和SLF4J在Java中打印日志的区别
  • Node.js是什么? 能做什么?
  • Harmony 开发与H5进行交互
  • OneNote不能拖动页面解决方案
  • docker-compose安装sentinel
  • Springcloud健身小程序-计算机毕业设计源码27368
  • linux中级wed服务器(https搭建加密服务器)
  • Spring Boot 中应用单元测试(UT):结合 Mock 和 H2 讲解和案例示范
  • (11)(2.1.7) FETtec OneWire ESCs(一)
  • idea git 一些日常操作解决办法(Git撤销回滚操作)
  • 【C语言】控制台学生成绩管理系统
  • 关系型数据库(1)----MySQL(初阶)
  • 大数据-189 Elasticsearch - ELK 日志分析实战 - 环境配置启动 Nginx、ZK、Kafka、ES、Kibana