我正在编写一个测试,看看我是否可以可靠地确定退出代码的整数值与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)
.