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

【Linux】—— 进程等待 waitwaitpid

序言:

 

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。因此,为了解决这个问题,就需要用到有关 “进程等待” 的基本知识!!!
 


目录

(一)进程的等待必要性

(二)进程等待的方法

1、wait方法

2、waitpid方法

(三)获取子进程status

 1、进程的阻塞等待方式

2、进程的非阻塞等待方式

总结


(一)进程的等待必要性

进程等待通常是指父进程等待子进程的执行完成。当一个进程创建了一个子进程,并希望在子进程执行完成后再继续执行自己的任务时,父进程需要等待子进程的完成。

以下是一些常见的原因和情况,需要进程等待:

  1. 避免僵尸进程:如果父进程不等待子进程完成而直接退出,子进程可能会成为僵尸进程。僵尸进程是已经完成执行但尚未被父进程回收的子进程。为了避免僵尸进程的产生,父进程需要等待子进程完成并回收子进程的资源

  2. 父子进程间通信:在使用fork()系统调用创建子进程时,父进程通常需要等待子进程完成,以确保获取子进程的执行结果或处理子进程的退出状态;

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

因此,我们可以得出进程等待就是:

  • 通过系统调用,获取子进程退出码或者退出信号的方式,顺便释放内存问题

(二)进程等待的方法

进程等待可以通过操作系统提供的函数来实现,主要有以下两种方法来进程等待操作:

  • waitpid函数:等待指定的子进程完成。可以设置选项参数来指定等待条件。
  • wait函数:等待任意一个子进程完成并获取其退出状态。

1、wait方法

遇到新的函数,如果不认识,就先去系统中查询一下:

 【说明】

  1. 返回值:成功返回被等待进程pid,失败返回-1。
  2. 参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
     

接下来,通过代码简单的

 int main(){pid_t id = fork();if(id == 0){//子进程int cnt = 5;while(cnt){printf("我是子进程,我还活着呢,我还有%dS, pid: %d, ppid%d\n", cnt    --, getpid(), getppid());sleep(1);}exit(0);}sleep(10);// 父进程pid_t ret_id = wait(NULL);printf("我是父进程,等待子进程成功, pid: %d, ppid: %d, ret_id: %d\n",getp    id(), getppid(), ret_id);    sleep(5);}

输出显示:

【解释】

  • 上述代码是一个简单的示例,展示了父进程创建子进程,并使用wait函数等待子进程完成。

进阶着又有一个问题:那就是父进程在 wait的时候,如果子进程没有退出,那么父进程在干什么呢?

我们把代码改一下看输出结果。代码如下:

 int main(){pid_t id = fork();if(id == 0){//子进程int cnt = 5;while(cnt){printf("我是子进程,我还活着呢,我还有%dS, pid: %d, ppid%d\n", cnt    --, getpid(), getppid());sleep(1);}exit(0);}// 父进程pid_t ret_id = wait(NULL);printf("我是父进程,等待子进程成功, pid: %d, ppid: %d, ret_id: %d\n",getp    id(), getppid(), ret_id);    sleep(5);}

输出显示:


2、waitpid方法

wait 和 waitpid 的头文件一样。具体如下:

pid_ t waitpid(pid_t pid, int *status, int options);


返回值
        1、当正常返回的时候waitpid返回收集到的子进程的进程ID;
        2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
       3、 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
     pid:
               1. Pid=-1,等待任一个子进程。与wait等效。
               2. Pid>0.等待其进程ID与pid相等的子进程。
     status:
        1.WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
        2.WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
     options:
        1.WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
 

  1. 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  2. 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  3. 如果不存在该子进程,则立即出错返回。
     

(三)获取子进程status

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

具体可以向下述这样理解: 

 

 

判断一个进程是否正常退出,只需要判断是否接收到进程终止信号大于0,异常退出,有进程终止信号;等于0,正常退出。 

代码演示:

int main()
{pid_t id = fork();if(id == 0){//子进程int cnt = 5;while(cnt){printf("我是子进程,我还活着呢,我还有%dS, pid: %d, ppid: %d\n", cnt--, getpid(), getppid());sleep(1);}exit(111);}                                                                                                                          // 父进程int status =0 ;pid_t ret_id = waitpid(id, &status, 0);printf("我是父进程,等待子进程成功, pid: %d, ppid: %d, ret_id: %d,child exit code: %d, child exit signal: %d\n"\,getpid(), getppid(), ret_id,(status>>8)&0xFF, status & 0x7F);sleep(2);
}

输出结果:


 1、进程的阻塞等待方式

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main()
{pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n",__FUNCTION__);return 1;} else if( pid == 0 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);} else{int status = 0;pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5Sprintf("this is test for wait\n");if( WIFEXITED(status) && ret == pid ){printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));}else{printf("wait child failed, return.\n");return 1;}}return 0;
}

输出展示:

 此运行结果是子进程正常退出的场景

2、进程的非阻塞等待方式

  1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include <sys/types.h>5 #include <sys/wait.h>6 7 int main()8 {9   pid_t pid;10   pid = fork();11   if(pid < 0){12     printf("%s fork error\n",__FUNCTION__);13     return 1;14   }else if( pid == 0 ){ //child15       printf("child is run, pid is : %d\n",getpid());16       sleep(5);17       exit(1);18     } else{19       int status = 0;20       pid_t ret = 0;21       do22       {23         ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待24         if( ret == 0 ){25         printf("child is running\n");26       }27       sleep(1);28       }while(ret == 0);29       if( WIFEXITED(status) && ret == pid ){30       printf("wait child 5s success, child return code is :%d.\n",WEXITS    TATUS(status));31       }else{32         printf("wait child failed, return.\n");33         return 1;34       }35     }                                                                   36   return 0;37 }38 

输出展示:

调用 waitpid 函数(非阻塞,WNOHANG)父子进程交替打印进行各自的循环,大概 5s 之后子进程, 可以看到子进程由 S+ 变成 Z+。

若WIFEXITED(status)为真---->进程正常退出

若WEXITSTATUS(status)>0---->WEXITSTATUS(status)表示子进程的退出码


总结

以上便是关于进程等待的全部知识了。感谢大家的观看与支持!!!

相关文章:

【Linux】—— 进程等待 waitwaitpid

序言&#xff1a; 之前讲过&#xff0c;子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成‘僵尸进程’的问题&#xff0c;进而造成内存泄漏。因此&#xff0c;为了解决这个问题&#xff0c;就需要用到有关 “进程等待” 的基本知识&#xff01;&#xff01;&am…...

el-tree 懒加载数据,增删改时局部刷新实现

1.数据过多时进行懒加载孩子节点&#xff0c;根据层级传参获取后端孩子数据 懒加载主要部分&#xff1a; 1参数: :load"loadNode" lazy :props"defaultProps" 2.defaultProps 需要设置isLeaf: isLeaf,去除最后一层孩子节点的展开图表 defaultProps: { ch…...

opencv基础44- Canny边缘检测详解-cv.Canny()

什么是Canny边缘检测&#xff1f; Canny边缘检测是一种经典的边缘检测算法&#xff0c;由John F. Canny在1986年提出。它被广泛应用于计算机视觉和图像处理领域&#xff0c;是一种多阶段的边缘检测算法&#xff0c;能够有效地检测图像中的边缘并抑制噪声。 Canny边缘检测的主要…...

neo4j查询语言Cypher详解(三)--函数

函数 Cypher中的函数如果输入参数为null&#xff0c;则返回null。 以字符串作为输入的函数都对Unicode字符进行操作&#xff0c;而不是对标准字符进行操作。例如&#xff0c;size()函数应用于任何Unicode字符将返回1&#xff0c;即使该字符不适合一个字符的16位。 可以通过 …...

kafka权威指南(阅读摘录)

零复制 Kafka 使用零复制技术向客户端发送消息——也就是说&#xff0c;Kafka 直接把消息从文件&#xff08;或者更确切地说是 Linux 文件系统缓存&#xff09;里发送到网络通道&#xff0c;而不需要经过任何中间缓冲区。这是 Kafka 与其他大部分数据库系统不一样的地方&#…...

【爬虫实践】使用Python从网站抓取数据

一、说明 本周我不得不为客户抓取一个网站。我意识到我做得如此自然和迅速&#xff0c;分享它会很有用&#xff0c;这样你也可以掌握这门艺术。【免责声明&#xff1a;本文展示了我的抓取做法&#xff0c;如果您有更多相关做法请在评论中分享】 二、计划策略 2.1 策划 确定您…...

win10 2022unity设置中文

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言解决方法 前言 在Edit->preferences里找不到language选项。 解决方法 【1】打开下面地址 注意 :把{version}换成你当前安装的版本&#xff0c;比如说如果…...

python表白代码大全可复制,python表白代码大全简单

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python表白代码大全可复制&#xff0c;python表白程序代码完整版&#xff0c;现在让我们一起来看看吧&#xff01; 今天是20230520&#xff0c;有人说&#xff1a;5代表的是人生五味&#xff0c;酸甜苦辣咸&#xff1b;…...

wordpress 打开缓慢处理

gravatar.com 头像网站被墙 追踪发现请求头像时长为21秒 解决方案一 不推荐&#xff0c;容易失效&#xff0c;网址要是要稳定为主&#xff0c;宁愿头像显示异常&#xff0c;也不能网址打不开 网上大部分搜索到的替换的CDN网址都过期了&#xff0c;例如&#xff1a;gravatar.du…...

Adobe ColdFusion 反序列化漏洞复现(CVE-2023-29300)

0x01 产品简介 Adobe ColdFusion是美国奥多比&#xff08;Adobe&#xff09;公司的一套快速应用程序开发平台。该平台包括集成开发环境和脚本语言。 0x02 漏洞概述 Adobe ColdFusion存在代码问题漏洞&#xff0c;该漏洞源于受到不受信任数据反序列化漏洞的影响&#xff0c;攻击…...

林【2018】

关键字: BST插入叶子结点、ADT结伴操作、队列插入前r-1、哈希函数二次探测法(1,-1,4,-4)、队列元素个数、折半查找失败次数、广义表链表结构、B-树构建、单链表指定位置插入数组元素 一、判断 二、单选 h(49)+1,-1,+4,-4...

ffmpeg+nginx实现rtsp协议摄像头web端播放

ffmpegnginx实现rtsp协议摄像头web端播放 环境准备准备nginx环境添加rtmp模块添加hls转发 使用ffmpeg&#xff0c;将摄像头rtsp转为rtmp并推送到nginxVLC播放验证 环境准备 nginx&#xff08;需要安装rtmp模块&#xff09;ffmpeg 6.0vlc播放器&#xff08;本地播放验证&#x…...

【周赛第69期】满分题解 软件工程选择题 枚举 dfs

目录 选择题1.2.3.4.面向对象设计七大原则 编程题S数最小H值 昨晚没睡好&#xff0c;脑子不清醒&#xff0c;痛失第1名 选择题 1. 关于工程效能&#xff0c;以下哪个选项可以帮助提高团队的开发效率&#xff1f; A、频繁地进行代码审查 B、使用自动化测试工具 C、使用版本控…...

P2015 二叉苹果树

P2015 二叉苹果树 类似于带限制背包问题&#xff0c;但不知道也能做。 n , q n,q n,q 范围小&#xff0c;大胆设 dp 状态。设 f u , i \large f_{u,i} fu,i​ 表示 u u u 子树内保留 i i i 根树枝的最大苹果数&#xff0c;可得状态转移方程 f u , i f u , j f v , i − …...

Linux 内核音频数据传递主要流程

Linux 用户空间应用程序通过声卡驱动程序&#xff08;一般牵涉到多个设备驱动程序&#xff09;和 Linux 内核 ALSA 框架导出的 PCM 设备文件&#xff0c;如 /dev/snd/pcmC0D0c 和 /dev/snd/pcmC0D0p 等&#xff0c;与 Linux 内核音频设备驱动程序和音频硬件进行数据传递。PCM 设…...

torch.device函数

torch.device 是 PyTorch 中用于表示计算设备&#xff08;如CPU或GPU&#xff09;的类。它允许你在代码中指定你希望在哪个设备上执行张量和模型操作&#xff0c;本文主要介绍了 torch.device 函数的用法和功能。 本文主要包含以下内容&#xff1a; 1.创建设备对象2.将张量和模…...

火车头采集器AI伪原创【php源码】

大家好&#xff0c;本文将围绕python作业提交什么文件展开说明&#xff0c;python123怎么提交作业是一个很多人都想弄明白的事情&#xff0c;想搞清楚python期末作业程序需要先了解以下几个事情。 火车头采集ai伪原创插件截图&#xff1a; I have a python project, whose fold…...

Python中常见的6种数据类型

数字&#xff08;Numbers&#xff09;&#xff1a;数字类型用于表示数值&#xff0c;包括整数&#xff08;int&#xff09;和浮点数&#xff08;float&#xff09;。 字符串&#xff08;Strings&#xff09;&#xff1a;字符串类型用于表示文本&#xff0c;由一系列字符组成。字…...

消息队列项目(2)

我们使用 SQLite 来进行对 Exchange, Queue, Binding 的硬盘保存 对 Message 就保存在硬盘的文本中 SQLite 封装 这里是在 application.yaml 中来引进对 SQLite 的封装 spring:datasource:url: jdbc:sqlite:./data/meta.dbusername:password:driver-class-name: org.sqlite.…...

解决MAC M1处理器运行Android protoc时出现的错误

Protobuf是Google开发的一种新的结构化数据存储格式&#xff0c;一般用于结构化数据的序列化&#xff0c;也就是我们常说的数据序列化。这个序列化协议非常轻量级和高效&#xff0c;并且是跨平台的。目前&#xff0c;它支持多种主流语言&#xff0c;比传统的XML、JSON等方法更具…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...