【进程等待】waitpid的参数pid | status的位图位操作WIFEXITEDWEXITSTATUS宏
目录
waitpid
pid
status
status位图
status按位操作
输入型参数和输入型参数
宏WIFEXITED&WEXITSTATUS
options&非阻塞等待
上篇进程等待我们介绍到怎样去进程等待。我们介绍了wait函数&阻塞等待。本篇我们将介绍waitpid函数的参数pid和status。
waitpid
- man 2 waitpid
- 等待一个进程的状态发生变化
- pit_t pid是父进程等待的子进程的pid,情况有3种,这里介绍两种情况。
- int *status是NULL
- int options是0
- 先把后面两个参数设置为NULL和0
pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
- 当正常返回的时候waitpid返回收集到的子进程的进程ID;
- 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
- 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
- Pid=-1,等待任一个子进程。与wait等效。
- Pid>0.等待其进程ID与pid相等的子进程。
status:
- WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
- WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
- WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
waitpid
是一个在Unix和类Unix系统(如Linux)中常用的系统调用,用于等待一个或多个子进程的状态改变。与wait
系统调用相比,waitpid
提供了更多的灵活性,因为它允许你指定要等待的子进程的PID(进程ID),并可以设置等待的模式(阻塞或非阻塞)。以下是
waitpid
函数的原型和参数详解:
pid_t waitpid(pid_t pid, int *status, int options);
pid
:这是一个整数,用于指定要等待的子进程的PID。其取值有以下几种情况:
pid > 0
:等待指定PID为pid
的子进程。pid = 0
:等待当前进程组中的任何子进程。pid = -1
:等待任何子进程,与wait
函数的功能相同。pid < -1
:等待组ID为-pid
的任意子进程。status
:这是一个指向整数的指针,用于存储子进程的退出状态。如果不需要这些信息,可以将此参数设置为NULL。options
:这是一个位掩码,用于修改waitpid
的行为。常见的选项有:
WNOHANG
:使waitpid
调用变为非阻塞。如果没有子进程满足条件,waitpid
会立即返回。WUNTRACED
:当子进程被停止时(而不是退出时),也返回它的状态。这通常与跟踪被调试的子进程有关。WCONTINUED
:当被停止的子进程恢复时,返回它的状态。
waitpid
的返回值有以下几种情况:
- 如果成功,返回收集到的子进程的PID。
- 如果设置了
WNOHANG
选项并且没有子进程满足条件,返回0。- 如果在调用中出现错误,返回-1,并设置全局变量
errno
以指示错误。
waitpid
是一个非常有用的工具,允许你更精细地控制和管理你的子进程。
pid
- 这样设置waitpid的参数,waitpid(-1,NULL,0)和 wait(NULL)的功能一致
- pid = -1表示等待任何一个子进程的退出
- pid > 0表示等待指定的一个子进程的退出
- pid为错误数字。wait fail !(只要pid不输入错误❌一般父进程都不会等待失败)
- fork返回值
- 0是子进程执行
- >0返回的是子进程的pid 是父进程执行(id是子进程的pid数值)
pid
:这是一个整数,用于指定要等待的子进程的PID。其取值有以下几种情况:
pid > 0
:等待指定PID为pid
的子进程。pid = 0
:等待当前进程组中的任何子进程。pid = -1
:等待任何子进程,与wait
函数的功能相同。pid < -1
:等待组ID为-pid
的任意子进程。
myprocess.c 1 #include<stdio.h>2 #include<unistd.h>3 #include<string.h>4 #include<stdlib.h>5 #include<sys/types.h>6 #include<sys/wait.h>7 8 void ChildRun()9 {10 int cnt = 5;11 while(cnt--)12 {13 printf("I am child,pid: %d,ppid: %d,cnt: %d\n",getpid(),getppid() ,cnt);14 sleep(1);15 }16 }17 18 int main()19 {20 printf("I am father,pid: %d,ppid: %d\n",getpid(),getppid());//父进> 程21 pid_t id = fork(); 22 if(id == 0)//child子进程23 {24 //子进程循环运行25 ChildRun();26 printf("Child quit...\n");27 exit(0);//终止进程,子进程直接僵尸28 }29 //father30 //父进程,父进程在子进程运行期间5ms一直在等待....31 //pid_t rid = wait(NULL); 32 pid_t rid = waitpid(id,NULL,0);33 if(rid > 0)34 {35 printf("wait success,rid: %d\n",rid);36 } 37 sleep(3);38 printf("father quit ... \n");39 }
【错误的pid演示】
//father31 //父进程,父进程在子进程运行期间5ms一直在等待.... 32 pid_t rid = waitpid(id+1 , NULL , 0);33 if(rid > 0)34 {35 printf("wait success,rid: %d\n",rid);36 }37 else38 {39 printf("wait fail !\n");40 }41 sleep(3);42 printf("father quit ... \n");
status
status
:这是一个指向整数的指针,用于存储子进程的退出状态。如果不需要这些信息,可以将此参数设置为NULL。
- int *status表示通过等待获取子进程的退出信息。(❗前面的进程终止已知进程终止的退出信息表示退出码&退出信号)
- 父进程通过waitpid等待子进程,通过第二个参数就可以拿到子进程的退出信息(status是输出型参数)
- 当然也存在父进程不关心子进程的退出信息,&status直接置为NULL即可。(等待是必须的,但是获取子进程的退出信息不是必须的)
- status不能简单的当作整形来看待,可以当作位图来看待,存在特定的格式。
- status是输出型参数。
- status按位操作拿到退出码和退出信号。
- status通过下面两个宏拿到退出码和退出信号。
- WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
- WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码。
有人问可不可以不用waitpid传递子进程的退出信息,直接定义两个全局变量exit_code,exit_signal。在子进程退出的时候写入自己的退出信息到全局变量当中❓
- 当然不可以,全局也是数据。虽然一开始是被父子进程共享,当子进程要写入的时候,会发生写时拷贝,此刻父子进程都有一份各自的全局变量的数据,父进程是看不到的子进程写入自己的全局变量的数据。
- 所以只能通过waitpid的status参数。下面我们来仔细学习以下☞☞
status位图
怎么把子进程的退出信息(退出码和退出信号)整合成一个数字赋值给status呢❓
- wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
- 如果传递NULL,表示不关心子进程的退出状态信息。
- 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
- status不能简单的当作整形来看待,可以当作位图来看待,存在特定的格式,32比特位具体细节如下图(只研究status低16比特位)
- 32比特位只使用低16比特位
- 其中次低8位:进程退出时所对应的退出状态(退出码)
- 其中最低7位:进程退出时是否受到终止信号(退出信号)
- 第8位:暂时不考虑,后面进程信号会讲
- 所以,退出状态的取值范围是[0,255],退出信号取值范围:[0,127]
- status是以位图的形式把子进程的退出码和退出信息返回给父进程的
在Linux的
waitpid
函数中,status
参数是一个指向整数的指针,它用于存储子进程的退出状态信息。尽管status
本身是一个整型指针,但我们更关心的是它所指向的那个整数变量的取值范围和内容。
- 这个整数变量(我们称之为
status_val
)通常用于表示子进程的退出状态。在大多数情况下,我们只关心这个整数的低16位,因为高16位通常不被使用。- 正常退出:如果子进程正常退出(即调用了
exit()
函数),那么status_val
的低16位的高8位将保存子进程的返回值(范围是0-255)。低8位中的低7位将被设置为0,而最高位(第8位)通常被用来表示一个标志位,以区分是正常退出还是由于信号而退出。- 异常退出:如果子进程由于接收到一个信号而退出,那么
status_val
的低16位的低7位将保存导致子进程退出的信号的编号(范围通常是1-127,但取决于系统和信号的具体实现)。同样,最高位(第8位)将用于表示是由于信号而退出。为了从
status_val
中提取这些信息,可以使用一些宏(如WEXITSTATUS
、WTERMSIG
等)来进行位操作和提取。因此,
status
本身并没有一个固定的取值范围,因为它只是一个指针。但它所指向的那个整数变量(status_val
)的取值范围和内容则取决于子进程的退出状态。
status按位操作
我们知道子进程的退出码和退出信息被父进程调用waitpid等待时,赋值给status参数。如果我们想要在父进程里面查看详细的子进程的退出码和退出信息🆗请看下面代码。
- 正常退出:(status>>8)&0xFF
- 异常退出:status&0x7F
- 解释☞位操作专题。
//....同上18 int main()19 {20 printf("I am father,pid: %d,ppid: %d\n",getpid(),getppid());//父进程21 pid_t id = fork();22 if(id == 0)//child子进程23 {24 //子进程循环运行25 ChildRun();26 printf("Child quit...\n");27 exit(1);//终止进程,子进程直接僵尸28 }29 //father30 //父进程,父进程在子进程运行期间5ms一直在等待.... 31 int status = 0;32 pid_t rid = waitpid(id, &status, 0);33 if(rid > 0)34 {35 printf("wait success,rid: %d\n",rid);36 }37 else38 {39 printf("wait fail !\n");40 }41 sleep(3);42 printf("father quit,status: %d,code: %d,signal: %d\n",status, (status>>8)&0XFF,status&0X7F); 43 }
【kill -9 pid错误测试】
【野指针错误测试】
输入型参数和输入型参数
在函数或系统调用的参数中,我们通常区分输入型参数(Input Parameters)和输出型参数(Output Parameters)。这些参数在函数或系统调用的执行过程中扮演不同的角色。
输入型参数(Input Parameters):
- 这些参数是函数或系统调用所需的信息或数据,用于执行特定的任务或操作。
- 它们通常由调用者(Caller)提供,并在函数或系统调用内部被使用。
- 输入型参数的值在函数或系统调用执行前后不会改变(除非函数或系统调用有特定的功能去修改它们)。
- 在
waitpid
函数中,pid
和options
是输入型参数。pid
指定了要等待的子进程的PID,而options
则设置了等待的行为(如阻塞或非阻塞)。输出型参数(Output Parameters):
- 这些参数用于存储函数或系统调用的结果或返回的数据。
- 它们通常在函数或系统调用执行前未定义或具有初始值,但在执行后被赋值或更新。
- 输出型参数的值在函数或系统调用执行后会被改变。
- 在
waitpid
函数中,status
是输出型参数。它用于存储子进程的退出状态信息,这些信息在函数执行前是未知的。总结:输入型参数是函数或系统调用所需的信息,而输出型参数则用于存储函数或系统调用的结果。在调用函数或系统调用时,正确设置输入型参数和处理输出型参数是非常重要的。
【输入型参数VS输出型参数】简而言之,输入型参数是调用者提供,输出型参数是程序赋值提供
宏WIFEXITED&WEXITSTATUS
除了用status通过按位操作来提取子进程的退出码和退出信号,有没有其他方法❓
- status按位操作不方便,介绍两个宏。(本质上就是status按位操作封装的)
- WIFEXITED(status): 若为正常终止子进程返回状态,则为真。查看进程是否是正常退出
- WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。查看进程的退出码
- WIFEXITED:W:wait IF:if EXITED:exited(等待退出)
- WEXITSTATUS:W:wait EXIT:exit STATUS:status(等待退出状态)
- 本质是:检查退出信号sign位也就是status的低7位是否位0,为0则是正常退出。非0则是异常退出。若是正常退出则若用户愿意可以用WEXITSTATUS查看退出码。
- ❗可以用这两个宏来判断是否退出为正常。
1: myprocess.c1 #include<stdio.h>2 #include<unistd.h>3 #include<string.h>4 #include<stdlib.h>5 #include<sys/types.h>6 #include<sys/wait.h>7 8 void ChildRun()9 { 10 int cnt = 5;11 while(cnt--)12 {13 printf("I am child,pid: %d,ppid: %d,cnt: %d\n",getpid(),getppid(),cnt);14 sleep(1);15 }16 }17 18 int main()19 {20 printf("I am father,pid: %d,ppid: %d\n",getpid(),getppid());//父进程21 pid_t id = fork();22 if(id == 0)//child子进程23 {24 //子进程循环运行25 ChildRun();26 printf("Child quit...\n");27 exit(1);//终止进程,子进程直接僵尸28 }29 //father30 //父进程,父进程在子进程运行期间5ms一直在等待.... 31 int status = 0;32 pid_t rid = waitpid(id, &status, 0);33 if(rid > 0)34 {35 if(WIFEXITED(status))36 {37 printf("child quit normal,child exit code: %d\n",WEXITSTATUS(status));38 }39 else40 {41 printf("child quit unnormal!\n");42 }43 printf("wait success,rid: %d\n",rid); 44 }45 else46 {47 printf("wait fail !\n");48 }49 sleep(3);50 //printf("father quit,status: %d,code: %d,signal: %d\n",status,(status>>8)&0XFF,status&0X7F);51 }
options&非阻塞等待
前面讲到在子进程运行期间,父进程一直在等待,能不能干点别的事情❓
options
:这是一个位掩码,用于修改waitpid
的行为。常见的选项有:
WNOHANG
:使waitpid
调用变为非阻塞。如果没有子进程满足条件,waitpid
会立即返回。WUNTRACED
:当子进程被停止时(而不是退出时),也返回它的状态。这通常与跟踪被调试的子进程有关。WCONTINUED
:当被停止的子进程恢复时,返回它的状态。
🙂感谢大家的阅读,若有错误和不足,欢迎指正。下篇阻塞等待和非阻塞等待以及waitpid的最后一个参数。
相关文章:

【进程等待】waitpid的参数pid | status的位图位操作WIFEXITEDWEXITSTATUS宏
目录 waitpid pid status status位图 status按位操作 输入型参数和输入型参数 宏WIFEXITED&WEXITSTATUS options&非阻塞等待 上篇进程等待我们介绍到怎样去进程等待。我们介绍了wait函数&阻塞等待。本篇我们将介绍waitpid函数的参数pid和status。 waitp…...
unity---常用API
1. Vector3:结构体由x、y、z这3个数值组成,表示一个向量 magnitude变量返回该向量的长度normalized变量返回 magnitude 为 1 时的该向量zero静态变量Vector3(0, 0, 0)one静态变量Vector3(1, 1, 1)forward静态变量Vector3(0, 0, 1)back静态变量Vector3(0…...

设计模式: 模板模式
目录 一,模板模式 二,特点 三,组成部分 四,实现步骤 五,案例 一,模板模式 模板模式(Template Pattern)是一种行为型设计模式,它在超类中定义了一个算法的骨架&#…...

[虚拟机+单机]梦幻契约H5修复版_附GM工具
本教程仅限学习使用,禁止商用,一切后果与本人无关,此声明具有法律效应!!!! 教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了 视频演示 [虚拟机单…...
头文件相互包含 前向声明
当两个类需要相互访问对方的成员或方法时,通常意味着它们之间存在某种依赖关系。这种依赖关系可能源于类的设计或功能需求。以下是一个简单的例子,展示了当两个类需要相互访问对方成员或方法时,如何使用包含对方头文件的方式来解决循环包含的…...

七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统
七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统 员工上班刷视频! 员工上班炒股! 员工上班干副业! 碰见这种情况怎么办?当然是用电脑监控软件来监视员工的一举一动了,那么这样的软件有哪些呢&#…...
centos7-bcc 安装
检查 内核信息 确保安装的kernel-dev 和内核版本一致!!! rpm -qa|grep kernel kernel-tools-3.10.0-1160.92.1.el7.x86_64 kernel-devel-3.10.0-1160.92.1.el7.x86_64 kernel-headers-3.10.0-1160.92.1.el7.x86_64 kernel-3.10.0-1160.92.1.el7.x86_64 kernel-tools-libs-3.1…...

5.06号模拟前端面试8问
5.06号模拟前端面试8问 1.promise如何实现then处理 在JavaScript中,Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:pending(等待),fulfilled(完成),rejected&…...
解读Inscode AI:开启代码智能化的新时代
导语: 近年来,人工智能技术的迅猛发展已经深刻地影响着各个行业,而在软件开发领域,Inscode AI的出现无疑将给代码智能化带来一场革命。本文将为大家解读Inscode AI的特点和应用,探索其如何改变我们的软件开发方式。 一…...
快速了解Vuex
Vuex Vuex使用Vuex Vuex 📌vuex 是一个专为 Vue.js 应用程序开发的状态管理库 📌vuex 可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能及时渲染到模板 📌vuex 采用集中式存储管理所有组件的状态…...

vue管理系统导航中添加新的iconfont的图标
1.在官网上将需要的图标,加入项目中,下载 2.下载的压缩包中,可以选择这两个,复制到项目目录中 3.如果和之前的iconfont有重复,那么就重新命名 4.将这里的.ttf文件,也重命名为自己的 5.在main文件中导入 6.在…...
Docker的介绍及与传统虚拟化技术的区别
Docker是一个开源的应用容器引擎,它使得开发者可以将应用及其依赖包打包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上。Docker基于Go语言开发,它的出现极大地简化了应用程序的部署、管理和扩展。 以下是Docker…...

06.Git远程仓库
Git远程仓库 #仓库种类,举例说明 github gitlab gitee #以这个仓库为例子操作登录码云 https://gitee.com/projects/new 创建仓库 选择ssh方式 需要配置ssh公钥 在系统上获取公钥输入命令:ssh-keygen 查看文件,复制公钥信息内…...

Anaconda安装和深度学习环境的安装(TensorFlow、Pytorch)
换了新电脑,重新装一下anaconda这些编程环境。好久没装过了,自己也需要查查资料,然后记录一下,分享给别人。 目标,三个环境:1.anaconda基础环境(包含xgboost和lightgbm),…...

元素设置 flex:1,但是会被内部长单词宽度超出拉伸
初始布局如上图,left中是代码编辑器,实际上是个文本域,当输入长文本过长时,left宽度会被拉伸。 右侧容器被挤压。 解决方案:width:0; .left{flex:1; width:0} 当输入长文本过长时,…...

win11 安装oracle11g详细流程及问题总结
1.安装包下载地址 本案例操作系统, Oracle 11g下载-Oracle 11g 64位/32位下载官方版(附详细的安装图解教程) - 多多软件站多多为大家免费提供Oracle 11g下载,包含64位/32位官方版本,并附详细的Oracle 11g安装图解教程,同时希望能…...
自我模拟面试
在面试中,你如何面对面试官呢? 我认为,对于面试官提出的问题,如果你不会,那就是不会。你的思考过程,实际上就是将你平时所学的,所了解的,在脑海中进行一次复习,就像当别…...
头歌java面向对象基础
第一关类的定义 package step1;// ---------------------Begin------------------------ public class Student{String name"李四";int age18;public void speak(){System.out.println("我爱学习");} }// ---------------------End----------------------…...

PMP课程知识点很多,无法入手,该如何学习?
回顾整个学习过程,我花费了不少时间,但也学到了系统的项目管理知识,考试结果也让我感到满意。在学习过程中,我认为以下几点非常重要: 1、需要对课本进行整体阅读,以便对内容有一个整体印象; 2…...

隔离流量优化网络传输
不要将长流和短突发流(或者大象流和老鼠流)混部在一起,我建议用切片或虚通道将它们在全链路范围彻底隔离,而不仅仅在交换机上配合着大肆宣讲的高端包分类算法配置一些排队调度。 也不必扯泊松到达,帕累托分布,这些概念在论文建模…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...