Как родительский процесс может узнать, был ли дочерний процесс завершен? - PullRequest
0 голосов
/ 02 апреля 2019

Я хочу написать программу, в которой родитель создает ровно 1 дочерний процесс. Дочерний процесс должен напечатать свой pid в стандартный вывод и затем завершить. Родительский процесс должен ждать, пока он не будет уверен, что дочерний процесс завершен. Родитель завершает работу после того, как он дождался дочернего процесса.

Вот что я получил до сих пор:

#include <unistd.h>     
#include <stdlib.h> 
#include <stdio.h>

int main(void) 
{ 
    int child;
    child = fork();
    if (child == 0)
        {
            printf("Child process has PID: %d. \n", getpid());
            exit(0);    
        }

        // how can the parent process find out it the child process was terminated successful? 

        printf("Child process terminated successfully\n");
        return EXIT_SUCCESS;

} 


Как родительский процесс может определить, был ли дочерний процесс завершен? Я не могу использовать wait () или waitpid () в этой программе.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Когда дочерний процесс завершает работу, сигнал SIGCHLD будет отправлен родителю, по умолчанию родитель игнорирует SIGCHLD, однако вы можете зарегистрировать обработчик сигнала, который его перехватит.

Вам нужно быть осторожным с тем, что вы делаете в обработчике сигналов - довольно много стандартных функций небезопасно для использования.

Подход SIGCHLD включается в код, когда у родителя есть своя собственная работа, и он не может просто ждать ребенка. Если родитель просто порождает детей, а затем ждет, пока они закончат, wait () и waitpid () являются лучшим решением.

Наконец, если вы не вызываете wait () или waitpid (), вы рискуете создать процесс зомби, дочерний процесс ожидает, что его родитель получит статус выхода через вызов одной из этих функций.

1 голос
/ 02 апреля 2019

Как я уже говорил, используйте сигнал SIGCHLD , например:

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

void handler(int sig)
{
  pid_t chpid = wait(NULL);

  /* WARNING : to show the call of the handler, do not do that
     in a 'real' code, we are in a handler of a signal */
  printf("Child pid %d ended (signal %s)\n", chpid, sig); 

  /* does 'something' to allow the parent to know chpid 
     terminated in a way compatible with parent requirement */
}

int main(void)
{
  signal(SIGCHLD, handler);

  if (!fork())
  {
    printf("Child pid is %d\n", getpid());
    sleep(1);
    return 0;
  }
  printf("Parent pid is %d\n", getpid());
  getchar();

  return 0;
}

Обратите внимание, что при поступлении сигнала необходимо позвонить wait (NULL) но поскольку по определению дочерний элемент завершается, функция немедленно возвращает

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra s.c
pi@raspberrypi:/tmp $ ./a.out
Parent pid is 21743
Child pid is 21744
Child pid 21744 ended (signal 17)
<enter>
pi@raspberrypi:/tmp $ 

Конечно, сигнал 17 равен SIGCHLD , поскольку он является единственнымпрограмма ловит

...