waitpid()设置WNOHANG位(非阻塞模式)判断子进程的状态是否有所改变
参考《Linux/Unix系统编程手册》26.1.5,对于系统调用waitid()
#include <sys/wait.h> int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
若在option中设置WNOHANG位,与那么该系统调用就是非阻塞的,也就是说会立刻返回而不是等待子进程的状态发生变化。
如果子进程的状态(正在运行or正常退出or被信号终止or被信号停止)发生变化,则会把状态具体信息保存在类型为siginfo_t结构的变量中。
PS:在sigaction处理信号时,也可以选用这个结构。
书上特意强调了一种情况,那就是,对于这种非阻塞操作假如子进程状态并未发生变化(也就是说正在运行,阻塞状态也可以算作未发生变化),infop指向的结构信息不会发生任何变化,因此需要预先memset将infop指向的结构每一位置为0,如果调用waitid()之后仍为0,则代表子进程状态未发生变化(简单来讲可理解为未退出)。
siginfo_t info;
// TODO:设置好waitid()的几个参数idtype、id、options
// ...
memset(&info, 0, sizeof(siginfo_t));
if (waitid(idtype, id, &info, options | WNOHANG) == -1)
// TODO: 错误处理
exit(1);
if (info.si_pid == 0) {
// 子进程状态未发生改变
} else {
// 子进程状态发生改变,状态信息存储到了info中
}
然后我就想到了,如果是使用waitpid()呢?
#include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options);
waitpid()仅仅将状态保存在int变量status中,书上很多代码是像这样
int status;
if (waitpid(pid, &status, options) == -1) {
// TODO: 错误处理
exit(1);
}
这有个问题,就是status并没有进行初始化,以前写C++的时候,记住的一条准则就是别忘记给变量赋初值。但是发现在很多C代码中都没有这个行为,之前在哪里看过这有利于检查错误,因为往往未赋初值的变量会导致错误,于是一直就这么写下来了。
于是我在写了份测试代码:调用fork()创建进程,子进程休眠1秒就_exit(1)退出,父进程则立刻调用waitpid(childPid, &status, WNOHANG);
理论上父进程的waitpid返回0(调用成功),因为childPid是对的,但是status状态千奇百怪,后来发现原因就是:子进程状态未发生改变时,status的值不变,于是status就是系统默认初始值(并未确定)。
按照waitid()的思路,就是给status一个初值,然后检查调用waitpid()调用后status的值是否发生了变化。
问题就来了,status该设为什么值呢?
其实这里设为-1就行了。
那么有人会问,如果_exit(-1);退出呢?
退出码是个1字节的整型,而int至少占2个字节,也就是初始状态为11111111 11111111
而如果waitpid()得到的status为-1,其实是1个字节,转换成2个字节int后就是11111111 00000000(小端模式下),和原来的-1有所不同。
实验结果也证明了这点

第1个结果是子进程阻塞,status不变,因此状态status为最初的-1,未知
第2个结果是父进程先阻塞再调用waitpid(),此时子进程已经_exit(-1)退出了,状态status经过WEXITSTATUS转换后是255,即(unsigned char)-1。
waitpid()设置WNOHANG位(非阻塞模式)判断子进程的状态是否有所改变的更多相关文章
- UDP socket 设置为的非阻塞模式
UDP socket 设置为的非阻塞模式 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct so ...
- 服务器编程心得(四)—— 如何将socket设置为非阻塞模式
1. windows平台上无论利用socket()函数还是WSASocket()函数创建的socket都是阻塞模式的: SOCKET WSAAPI socket( _In_ int af, _In_ ...
- 看到关于socket非阻塞模式设置方式记录一下。
关于socket的阻塞与非阻塞模式以及它们之间的优缺点,这已经没什么可言的:我打个很简单的比方,如果你调用socket send函数时: 如果是阻塞模式下: send先比较待发送数据的长度len和套接 ...
- 非阻塞模式ServerSocketChannel 聊天室服务器端
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import ja ...
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
- 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .
命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...
- linux-socket connect阻塞和非阻塞模式 示例
~/cpp$ ./connect 192.168.1.234 1234 kkkk block mode: ubuntu 14.04 : time used:21.0.001053s connect ...
- PHP非阻塞模式 (转自 尘缘)
让PHP不再阻塞当PHP作为后端处理需要完成一些长时间处理,为了快速响应页面请求,不作结果返回判断的情况下,可以有如下措施: 一.若你使用的是FastCGI模式,使用fastcgi_finish_re ...
- Socket 阻塞模式和非阻塞模式
阻塞I/O模型: 简介:进程会一直阻塞,直到数据拷贝 完成 应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好. 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返 ...
随机推荐
- 【2018 “百度之星”程序设计大赛 - 初赛(B)- 1001】degree
Problem Description 度度熊最近似乎在研究图论.给定一个有 N 个点 (vertex) 以及 M 条边 (edge) 的无向简单图 (undirected simple graph) ...
- 【Html 学习笔记】第五节——表格
表格也是日常用到的. 普通表格:<table> 表格边框:border 表头:th 表格标题:caption 横/纵向合并的单元格:colspan .rawspan 表格内标签: 单元格间 ...
- C++(笔记)浅析vector容器的实例
http://www.runoob.com/w3cnote/cpp-vector-container-analysis.html 转载请注明出处 浅然的专栏 https://blog.csdn.net ...
- Ubuntu 14.10安装simplescalar
经过两天的安装,终于把simplescalar安装成功,安装过程中在网上找了很多资料,但是很多都是关于低版本ubuntu安装的过程,而且按照这些教程也没有安装成功,来记录一下安装中出现的问题及解决方案 ...
- Linux下系统的定时及延时任务
一.系统的延时 是临时的.对系统做的任务指定一个时间点.发起的命令是at at 时间点(now+1min) ## 设定任务实行时间 at> 执行命令 ...
- MFC CListControl 点击列头排序的实现
SetItemData可以为每一行绑定一个DWORD类型的变量.用GetItemData可以获得这个变量.举个例子,假设CListCtrl中你需要显示某个数据表中的记录,该表有个流水号主键ID,一般这 ...
- 评价指标的计算:accuracy、precision、recall、F1-score等
记正样本为P,负样本为N,下表比较完整地总结了准确率accuracy.精度precision.召回率recall.F1-score等评价指标的计算方式: (右键点击在新页面打开,可查看清晰图像) 简单 ...
- 汇编语言---键盘KeyCode值列表
键盘KeyCode值列表 收藏 keycode 0 =keycode 1 =keycode 2 =keycode 3 =keycode 4 =keycode 5 =keycod ...
- Failed to resolve: com.android.support:appcompat-v7:27.+ 报错解决方法
最近在学习Android方面的编程,这个过程中出现了许多的错误,其中最多的错误是出现在构建工具进行编译的时候.这里分析一个出现的错误,Failed to resolve: com.android.su ...
- [interview]螺旋队列问题
摘要 本文主要讲解三种螺旋队列的实现方式和打印输出: 从中心往外端顺时针旋转,记为『外螺旋队列』 从左顶点开始,绕剩下的最大圈顺时针往内旋转,记为『内螺旋队列』 从左顶点开始,之字形旋转(只能同行同列 ...