Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

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

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--] = '\0';

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
. Это примитивно, но работает.

41 /* childhandler --- перехват SIGCHLD, сбор сведений со всех доступных потомков */

42

43 void childhandler(int sig)

44 {

45 int status, ret;

46 int i;

47 char buf[100];

48 static const char entered[] = "Entered childhandler\n" ;

49 static const char exited[] = "Exited childhandler\n";

50

51 writed, entered, strlen(entered));

52 for (i =0; i < nkids; i++) {

53 if (kids[i] == NOT_USED)

54 continue;

55

56 retry:

57 if ((ret = waitpid(kids[i], &status, WNOHANG)) == kids[i]) {

58 strcpy(buf, "\treaped process ");

59 strcat(buf, format_num(ret));

60 strcat(buf, "\n");

61 write(1, buf, strlen(buf));

62 kids[i] = NOT_USED;

63 } else if (ret == 0) {

64 strcpy(buf, "\tpid ");

65 strcat(buf, format_num(kids[i]));

66 strcat(buf, " not available yet\n");

67 write(1, buf, strlen(buf));

68 } else if (ret == -1 && errno == EINTR) {

69 write(1, "\tretrying\n", 10);

70 goto retry;

71 } else {

72 strcpy(buf, "\twaitpid failed: ");

73 strcat(buf, strerror(errno));

74 strcat(buf, "\n");

75 write(1, buf, strlen(buf));

76 }

77 }

78 write(1, exited, strlen(exited));

79 }

Строки 51 и 58 выводят «входное» и «завершающее» сообщения, так что мы можем ясно видеть, когда вызывается обработчик сигнала. Другие сообщения начинаются с ведущего символа TAB.

Главной частью обработчика сигнала является большой цикл, строки 52–77. Строки 53–54 проверяют на

NOT_USED
и продолжают цикл, если текущий слот не используется.

Строка 57 вызывает

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

Основываясь на возвращенном значении, код предпринимает соответствующее действие. Строки 57–62 обрабатывают случай обнаружения потомка, выводя сообщение и помещая в соответствующий слот в

kids
значение
NOT_USED
.

Строки 63–67 обрабатывают случай, когда затребованный потомок недоступен. В этом случае возвращается значение 0, поэтому выводится сообщение, и выполнение продолжается.

Строки 68–70 обрабатывают случай, при котором был прерван системный вызов. В этом случае самым подходящим способом обработки является

goto
обратно на вызов
waitpid
. (Поскольку
main
блокирует все сигналы при вызове обработчика сигнала [строка 96], это прерывание не должно случиться. Но этот пример показывает, как обработать все случаи.)

Поделиться:
Популярные книги

Шайтан Иван 4

Тен Эдуард
4. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
8.00
рейтинг книги
Шайтан Иван 4

Язычник

Мазин Александр Владимирович
5. Варяг
Приключения:
исторические приключения
8.91
рейтинг книги
Язычник

Последний реанорец. Том I и Том II

Павлов Вел
1. Высшая Речь
Фантастика:
фэнтези
7.62
рейтинг книги
Последний реанорец. Том I и Том II

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Путь Шедара

Кораблев Родион
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Путь Шедара

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Алые перья стрел

Крапивин Владислав Петрович
Детские:
детские приключения
8.58
рейтинг книги
Алые перья стрел

Я спас ссср! том iv

Вязовский Алексей
4. Я спас СССР
Фантастика:
альтернативная история
6.62
рейтинг книги
Я спас ссср! том iv

Лейтенант. Часть 2. Назад в СССР

Гаусс Максим
9. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Лейтенант. Часть 2. Назад в СССР

Кодекс Охотника. Книга XXV

Винокуров Юрий
25. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга XXV

Хозяин теней 2

Демина Карина
2. Громов
Фантастика:
аниме
попаданцы
фэнтези
7.00
рейтинг книги
Хозяин теней 2

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон