C,退出和pcntl_wait函数产生 256 的倍数,为什么


C, exit and pcntl_wait functions produce multiples of 256, why?

我正在编写一个测试,看看我是否可以可靠地确定退出代码的整数值与wait.

问题

1. 为什么退出代码乘以 256?
2. exit()wait()、操作系统或其他东西在做乘法吗?

重现问题的代码。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// implementation is correct but irrelevant to the question
int compareInt(const void* a, const void* b); 
int main(void) {
    pid_t pids[6];
    int i;
    for (i = 0; i < 6; i++) {
        pid_t pid = fork();
        pids[i] = pid;
        if (pid == 0) {
            exit(i);
        }
    }
    int codes[6];
    do {
        i--;
        wait(&codes[i]);
    } while (i > 0);
    const size_t num_elem = 6;
    qsort(codes, num_elem, sizeof(int), compareInt);
    for (i = 0; i < 5; i++) {
        printf("%d, ", codes[i]);
    }
    printf("%d'n", codes[5]);
    return 0;
}

输出:0, 256, 512, 768, 1024, 1280

事实证明,我应该使用wifexited(), wifstopped(), wifsignaled(), wexitstatus(), wtermsig(), or wstopsig()来确定退出状态。

此外,相同的行为在PHP中是可重现的(我第一次遇到它的地方)

$pids = [];
foreach (range(0, 5) as $i) {
    $pids[] = $pid = pcntl_fork();
    if ($pid === 0) {
        exit($i);
    }
}
$exit_codes = [];
do {
    pcntl_wait($exit_codes[]);
    array_pop($pids);
} while (count($pids) > 0);
sort($exit_codes);
echo implode(', ', $exit_codes) . "'n";

输出:0, 256, 512, 768, 1024, 1280

如果它有所作为,我正在运行 Ubuntu 14.04,man wait说我有WAIT(2)

您看到这些结果的原因是,来自wait()的返回值是经过编码的,并且包含诸如进程停止的方式和原因以及实际退出状态等信息; 这就是为什么提供方便宏来检查返回值的某些部分的原因。

WEXITSTATUS(status)的定义可以在sys/wait.h中找到,可能如下所示:

#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)

或者这个:

#define WEXITSTATUS(status) (((status) >> 8) & 0x000000ff)

所以你看到乘法是因为:

exit(1) -> 0x0100 (256)
exit(2) -> 0x0200 (512)

在PHP中,你将使用pcntl_wexitstatus()来完成同样的事情;如果进程由于信号而被终止,则不会有退出状态,你需要使用pcntl_wtermsig()来确定用于终止它的信号。

wait() 的返回值对多条信息进行编码。定义了宏来挑选结果并仅获得所需的尼特。例如 WEXITSTATUS(result_of_wait) .