waitpid(pid_t pid, int *status, int options) 的第二个参数用来标识导致 waitpid 返回的子进程的状态,一般而言这是一个 32 位的量(也有例外,比如 ptrace event 会用到更高位的字节来标识 event),有以下四种情况(应该是和编译器实现有关,但至少 gcc 是这样):
子进程正常退出,例如 exit,此时 status 的结构是
xxxx xxxx y000 0000,前八位表示 exit codeWIFEXITED宏用来判断是否为该情况,WEXITSTATUS宏用来获取 exit code子进程由于收到信号而终止,此时 status 的结构是
0000 0000 xyyy yyyy,后七位不能全为 0 或全为 1,且后七位表示导致终止的信号值,此外 x 为 1 的话表示 core dumpedWIFSIGNALED宏用来判断是否为该情况,WTERMSIG宏用来获取信号值,WIFSIGNALED宏的实现很精彩:Code1
#define __WIFSIGNALED(status) (((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
如果后七位全为 0,与
0x7f取与后再加 1,就变成0x01,再右移一位就是 0,返回 false如果后七位全为 1,与
0x7f取与后再加 1,就变成0x80,重点在于类型转成了 signed char,右移的话1000 0000就成了1100 0000(如果是 unsigned 就是0100 0000),符号位是 1,为负,返回 false子进程由于收到信号而暂停,此时 status 结构是
xxxx xxxx 0111 1111,前八位表示收到的信号值WIFSTOPPED宏用来判断是否为该情况,WSTOPSIG宏用来获取信号值。一般出现这种情况是因为使用了 ptrace 或者 waitpid 的第三个参数指定了
WUNTRACED子进程由于收到 SIGCONT 信号而即将继续,此时 status 结构是
1111 1111 1111 1111WIFCONTINUED宏用来判断是否为该情况