ОС: ожидание () в дочернем процессе

#c #operating-system #wait #child-process

#c #операционная система #подождите #дочерний процесс

Вопрос:

Изучая ОС, обычно в любых учебниках было замечено, что для создания дочернего процесса используется fork() в родительском процессе, а иногда вызывается wait() в родительском, чтобы дождаться завершения дочернего процесса.

Но что произойдет, если я использую wait() в дочернем процессе?

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

int
main(int argc, char** argv){
  int x;
  int w1, w2;
  x = 100;
  printf("the initialized x is: %dn",x);
  int rc = fork();
  if(rc < 0){
    fprintf(stderr, "fork failed.n");
    exit(1);
  }
  else if(rc == 0){
    //x = 200;                                                                  
    w1 = wait(NULL);
    printf("the x in child process (pid:%d) is: %dn", (int) getpid(), x);
  } else {
    x = 300;
    w2 = wait(NULL);
    printf("the x in parent process (pid:%d) is: %dn",(int) getpid(), x);
  }
  printf("the x in the end is: %dn",x);
  printf("the returns of waits: %d, %dn",w1,w2);
  return 0;
}
  

Этот фрагмент кода выполняется и показывает следующее:

 dhcp175:hw_ch5 Suimaru$ ./a.out 
the initialized x is: 100
the x in child process (pid:18844) is: 100
the x in the end is: 100
the returns of waits: -1, 0
the x in parent process (pid:18843) is: 300
the x in the end is: 300
the returns of waits: 0, 18844
  

Как это объяснить?

Ответ №1:

Но что произойдет, если я использую wait() в дочернем процессе?

Вы читали его документацию? Особенно части о возвращаемом значении и условиях ошибки? Я вижу, что вы провели эксперимент, и это хорошо; между этим и документами уже должно быть ясно, что если у вызываемого процесса wait() нет дочерних процессов, которые нужно ожидать, то он немедленно возвращается -1 , указывая на ошибку. В этом случае errno будет установлено значение ECHILD .

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

Ответ №2:

Вы уже сказали, что происходит в вашем примере вывода, но для получения более подробной информации вы должны проверить errno значение после получения кода сбоя из wait системного вызова. Хотя проверка if (errno == ECHILD) полезна и может использоваться для выполнения некоторых действий, которые могут обработать эту ошибку, вы также можете получить строку (массив символов) с сообщением об ошибке, используя следующий код:

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

...

char err_msg[4096]; // a buffer big enough to hold an error message
errno = 0; // clear errno just in case there was an earlier error
pid_t fpid = fork();
if (fpid < 0)
{
    perror("fork failed.n"); // prints out an error string based on errno
    exit(1);
} else if (fpid == 0)
{ // in child
    pid_t wpid = wait(NULL);                                                             
    strerror_r(errno, err_msg, sizeof(err_msg)); // gets an error string
    printf("child process (pid:%d), wpid:%d, %sn", (int) getpid(), (int)wpid, err_msg);
} else {
    int err_val;
    wpid = wait(NULL);
    err_val = errno;
    errno = 0; // reset errno
    strerror_r(err_val , err_msg, sizeof(err_msg)); // gets an error string
    printf("parent process (pid:%d), wpid:%d, %sn", (int) getpid(), (int)wpid, err_msg);
    if (err_val != 0)
    {
        // there was an error, so what are you going to do about it?
    }
}