Книга: Основы программирования в Linux

Ожидание процесса

Ожидание процесса

Когда вы запускаете дочерний процесс с помощью вызова fork, он начинает жить собственной жизнью и выполняется независимо. Иногда вам нужно знать, когда закончился дочерний процесс. Например, в предыдущей программе родительский процесс завершается раньше дочернего, и вы получаете слегка беспорядочный вывод, потому что дочерний процесс продолжает выполняться. Вы можете с помощью системного вызова wait заставить родительский процесс дождаться завершения дочернего процесса перед своим продолжением.

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *stat_loc);

Системный вызов wait заставляет родительский процесс сделать паузу до тех пор, пока один из его дочерних процессов не остановится. Вызов возвращает PID дочернего процесса. Обычно это дочерний процесс, который завершился. Сведения о состоянии позволяют родительскому процессу определить статус завершения дочернего процесса, т.е. значение, возвращенное из функции main или переданное функции exit. Если stat_loc не равен пустому указателю, информация о состоянии будет записана в то место, на которое указывает этот параметр.

Интерпретировать информацию о состоянии процесса можно с помощью макросов, описанных в файле sys/wait.h и приведенных в табл. 11.2.

Таблица 11.2

Макрос Описание
WIFEXITED(stat_val) Ненулевой, если дочерний процесс завершен нормально
WEXITSTATUS(stat_val) Если WIFEXITED ненулевой, возвращает код завершения дочернего процесса
WIFSIGNALED(stat_val) Ненулевой, если дочерний процесс завершается неперехватываемым сигналом
WTERMSIG(stat_val) Если WIFSIGNALED ненулевой, возвращает номер сигнала
WIFSTOPPED(stat_val) Ненулевой, если дочерний процесс остановился
WSTOPSIG(stat_val) Если WIFSTOPPED ненулевой, возвращает номер сигнала

Выполните упражнение 11.4.

Упражнение 11.4. Системный вызов wait

В этом упражнении вы слегка измените программу, чтобы можно было подождать и проверить код состояния дочернего процесса. Назовите новую программу wait.c.

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
 pid_t pid;
 char* message;
 int n;
 int exit_code;
 printf("fork program startingn");
 pid = fork();
 switch(pid) {
 case -1:
  perror("fork failed");
  exit(1);
 case 0:
  message = "This is the child";
  n = 5;
  exit_code = 37;
  break;
 default:
  message = "This is the parent";
  n = 3;
  exit_code = 0;
  break;
 }
 for (; n > 0; n--) {
  puts(message);
  sleep(1);
 }

Следующий фрагмент программы ждет окончания дочернего процесса:

 if (pid != 0) {
  int stat_val;
  pid_t child_pid;
  child_pid = wait(&stat_val);
  printf("Child has finished: PID = %dn", child_pid);
  if (WIFEXITED(stat_val))
   printf("Child exited with code %dn", WEXITSTATUS(stat_val));
  else printf("Child terminated abnormallyn");
 }
 exit(exit_code);
}

Когда вы выполните эту программу, то увидите, что родительский процесс ждет дочерний:

$ ./wait
fork program starting
This is the child
This is the parent
This is the parent
This is the child
This is the parent
This is the child
This is the child
This is the child
Child has finished: PID = 1582
Child exited with code 37
$

Как это работает

Родительский процесс, получивший ненулевое значение, возвращенное из вызова fork, применяет системный вызов wait для приостановки своего выполнения до тех пор, пока информация о состоянии дочернего процесса не станет доступной. Это произойдет, когда дочерний процесс вызовет функцию exit; мы присвоили ему код завершения 37. Далее родительский процесс продолжается, определяет, протестировав значение, возвращенное вызовом wait, что дочерний процесс завершился нормально, и извлекает код завершения из информации о состоянии процесса.

Оглавление книги


Генерация: 0.633. Запросов К БД/Cache: 2 / 0
поделиться
Вверх Вниз