先看下面的代码段:
static int system2(const char *command) { pid_t pid; int status; pid = fork(); if (pid == 0) { int null = open("/dev/null", O_RDWR); dup2(null, 0); dup2(null, 3); if (null > 2) close(null); if (null == 3) fprintf(stderr, "fd3 is closed in the forked process\n"); status = system(command); if (null <= 2) close(null); _exit(WEXITSTATUS(status)); } for(;;) { pid = waitpid(pid, &status, 0); if (pid < 0) { perror("waitpid"); fprintf(stderr, "Unexpected error: waitpid: %s", strerror(errno)); status = -1; } else if (WIFSTOPPED(status)) { continue; } break; } return status; }
上面代码中,waitpid返回的status中,共有16位,高8位代表子进程退出码(0-255,0代表正常退出,非0一般是非正常退出),低8位代表子进程的原因,是信号触发,还是自己正常退出(0为正常退出,0x7F为STOP,0x80为KILL强行退出)。
所以WIFSTOPPED这个宏就是用来判断第8位是否为0x7F。
子进程调用system函数,然后期望将system的返回码(孙子进程退出状态)进一步返回给父进程。system的返回值应该也有16位信息,高8位为退出码,低8位为退出原因。在将这个孙子进程的退出状态返回给父进程时,调用了_exit()函数,这时,需要提取高8位,所以得用宏WEXITSTATUS。
上面宏的有关定义如下:
#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) #define WCOREDUMP(s) ((s) & 0x80) #define WTERMSIG(s) ((s) & 0x7f) #define WSTOPSIG(s) WEXITSTATUS(s) #define WIFEXITED(s) (WTERMSIG(s) == 0) #define WIFSTOPPED(s) (WTERMSIG(s) == 0x7f) #define WIFSIGNALED(s) (WTERMSIG((s)+1) >= 2)