关于system/exit/wait的解释
最后从system2的返回值,期待跟原生system的返回值类似,具有退出码和退出原因,以便客户端代码进一步用相关宏来判断。
先看下面的代码段:
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)
最后从system2的返回值,期待跟原生system的返回值类似,具有退出码和退出原因,以便客户端代码进一步用相关宏来判断。