Почему wait() возвращает два нуля?

Почему wait() возвращает два нуля?

23.06.2016 11:01:39 Просмотров 25 Источник
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

main(){
   int pid1, pid2, status;

   pid1 = fork();
   if (pid1 == 0){ /* proces potomny */
      sleep(10);
      exit(7);
   }
   /* proces macierzysty */
   printf("Ребенок с идентификатором %d\n", pid1);
   kill(pid1, 9);
   pid2 = wait(&status);
   printf("Статус окончания процесса %d: %x\n", pid2, status);
}

в итоге если я передам wait(7) - 700 (статус), а если хоть 32, то 20 00. Я понимаю что это из-за перевода в 16ю. Но если я допустим ввиду тип %d то вообще будет 8192, непонятно совсем с этим. И откуда постоянно берутся эти два нуля.Один ноль это видимо, потому, что на самом деле ошибки не было, а вот второй совсем непонятно откуда.

У вопроса есть решение - Посмотреть?

Ответы - Почему wait() возвращает два нуля? / Почему wait() возвращает два нуля?

VladD

23.06.2016 11:13:35

Дело в том, что результат работы wait представляет собой битовое поле, кодирующее различную информацию о процессе. Конкретные номера битов не так важны, для извлечения информации нужно, согласно документации, использовать макросы WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG и тому подобные.

Если вы хотите извлечь код завершения, проверьте сначала if (WIFEXITED(status)), при положительном исходе проверки берите WEXITSTATUS(status).


Судя по всему, на POSIX-системах из кода завершения процесса (то, что передаётся в exit), игнорируется всё, кроме кроме младшего байта. Так что если вы скажете exit(257), это всё равно, что exit(1).

Обновление: согласно Википедии, полностью аргумент exit можно таки вытянуть через waitid.

avp

23.06.2016 11:48:31

Вам уже ответили, что так извлекать код завершения процесса неправильно.

Более того, Ваша программа всегда принудительно завершает процесс потомка и в status всегда будет код сигнала -- 9.

Вот немного переделанная Ваша программа

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>

int
main (int ac, char *av[])
{
   int status;
   pid_t pid1, pid2;

   pid1 = fork();
   if (pid1 == 0){ /* proces potomny */
      sleep(1);
      exit(atoi(av[1] ? av[1] : "0"));
   }
   /* proces macierzysty */
   printf("Ребенок с идентификатором %d\n", (int)pid1);
   if (av[1] && av[2]) 
     if (kill(pid1, atoi(av[2])))
       printf("kill: %m\n"); // some error
     else
       printf("send signal %d to  child\n", atoi(av[2]));
   else
     puts("wait for child exit");

   pid2 = wait(&status);
   int rc = -1; // undefined
   const char *msg = "exited";
   if (WIFEXITED(status))
     rc = WEXITSTATUS(status);
   else if (WIFSIGNALED(status)) {
     rc = WTERMSIG(status);
     msg = "terminated";
   } else // WIFSTOPPED or WIFCONTINUED
     msg = "stopped | continued";

   printf("Статус окончания процесса %d: 0x%x (%s)\n", 
      (int)pid2, rc, msg);

   return puts("End") == EOF;
}

которая в первом аргументе принимает код, с которым нормально (вызывая exit()) завершается потомок, а во втором (если он задан) номер сигнала, который родитель посылает потомку.

Можете оттранслировать (gcc или g++, если хотите) и посмотреть ее вывод.

P.S.
список сигналов можно увидеть, вызвав в шелле команду kill -l
а также, пример кода обработки завершения процесса приведен в man 2 wait

Закрыть X