Функции C, exit и pcntl_wait дают кратные 256, почему?

Я писал тест, чтобы увидеть, могу ли я надежно определить целочисленное значение кода выхода
с 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)

6

Решение

Причины, по которым вы видите эти результаты, в том, что возвращаемое значение из 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() определить сигнал, который был использован, чтобы убить его.

11

Другие решения

Возвращаемое значение wait() кодирует несколько частей информации. Существуют макросы, предназначенные для разделения результатов и получения необходимой информации. например WEXITSTATUS(result_of_wait),

1

По вопросам рекламы [email protected]