👀 📔 читать онлайн » Компьютеры и Интернет » Программирование » Linux программирование в примерах - Роббинс Арнольд

Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"

Перейти на страницу:

10.8.3. Родительский надзор: три различные стратегии

Как описано в разделе 9.1.1 «Создание процесса:

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

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

SIGCHLD
[112]. Действием по умолчанию является игнорирование этого сигнала. В этом случае процессы зомби накапливаются до тех пор, пока родитель не вызовет
wait()
или не закончится сам. В последнем случае процессы зомби получают в качестве нового родителя системный процесс
init
(PID 1), который получает от них результаты как часть своей обычной работы. Сходным образом, активные потомки также получают родителем
init
, и их результаты будут собраны при их завершении.

SIGCHLD
используется для большего, чем уведомление о завершении потомка. Каждый раз при остановке потомка (посредством одного из обсужденных ранее сигналов управления заданиями) родителю также посылается
SIGCHLD
. Стандарт POSIX указывает, что
SIGCHLD
«может быть послан» также, когда помок вновь запускается; очевидно, среди оригинальных Unix-систем имеются различия.

Сочетание флагов для поля

sa_flags
  в
struct sigation
и использование
SIG_IGN
в качестве действия для
SIGCHLD
позволяет изменить способ обработки ядром остановок, возобновления или завершения потомков.

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

10.8.3.1. Плохие родители: полное игнорирование потомков

Простейшим действием, которое вы можете сделать, является изменение действия для

SIGCHLD
на
SIG_IGN
. В этом случае завершившиеся потомки не становятся зомби. Вместо этого статус их завершения отбрасывается, и они полностью удаляются из системы.

Другой возможностью, дающей такой же результат, является использование флага

SA_NOCLDWAIТ
. В коде:

/* Старый стиль: */        /* Новый стиль: */

signal(SIGCHLD, SIG_IGN);  struct sigaction sa;

                           sa.sa_handler = SIG_IGN;

                           sa.sa_flags = SA_NOCLDWAIT;

                           sigemptyset(&sa.sa_mask);

                           sigaction(SIGCHLD, &sa, NULL);

10.8.3.2. Снисходительные родители: минимальный надзор

В качестве альтернативы можно беспокоиться лишь о завершении потомка и не интересоваться простыми изменениями состояния (остановке и возобновлении). В этом случае используйте флаг

SA_NOCLDSTOP
и установите обработчик сигнала, вызывающий
wait()
(или родственную ей функцию) для получения данных процесса.

В общем вы не можете ожидать получать по одному сигналу

SIGCHLD
на каждого завершающегося потомка. Следует считать, что
SIGCHLD
означает «завершился по крайней мере один потомок» и быть готовым собрать при обработке
SIGCHLD
сведения о как можно большем числе потомков.

Следующая программа,

ch10-reap1.с
, блокирует
SIGCHLD
до тех пор, пока не будет готова восстановить потомков.

1  /* ch10-reap1.с --- демонстрирует управление SIGCHLD с использованием цикла */

2

3  #include <stdio.h>

4  #include <errno.h>

5  #include <signal.h>

6  #include <string.h>

7  #include <sys/types.h>

8  #include <sys/wait.h>

9

10 #define MAX_KIDS 42

11 #define NOT_USED -1

12

13 pid_t kids[MAX_KIDS];

14 size_t nkids = 0;

Массив потомков отслеживает ID порожденных процессов. Если элемент содержит

NOT_USED
, он не представляет необработанного потомка. (Его инициализируют строки 89–90 внизу)
nkids
указывает, сколько значений в
kids
следует проверить.

16 /* format_num --- вспомогательная функция, поскольку нельзя использовать [sf]printf() */

17

18 const char *format_num(int num)

19 {

20 #define NUMSIZ 30

21  static char buf[NUMSIZ];

22  int i;

23

24  if (num <= 0) {

25   strcpy(buf, "0");

26   return buf;

27  }

28

29  i = NUMSIZ - 1;

30  buf[i--] = '';

31

32  /* Преобразует цифры обратно в строку. */

33  do {

34   buf[i--] = (num % 10) + '0';

35   num /= 10;

36  } while (num > 0);

37

38  return &buf[i+1];

39 }

Поскольку обработчики сигналов не должны вызывать функции семейства

printf()
, мы предусмотрели для преобразования десятичного сигнала или номера PID в строку простую «вспомогательную» функцию
format_num()
. Это примитивно, но работает.

Перейти на страницу:
Оставить комментарий о книге
Подтвердите что вы не робот:*

Отзывы о книге "Linux программирование в примерах, автор: Роббинс Арнольд":

Все материалы на сайте размещаются его пользователями. Администратор сайта не несёт ответственности за действия пользователей сайта. Вы можете направить вашу жалобу на почту booksreadonlinecom@gmail.com
© 2021 - 2026 booksread-online.com