Принудительное завершение подпроцессов - пример



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

13-17     Запускаются пять подпроцессов, и их идентификаторы записываются в chpid[].

19-26     wait(2) в цикле ожидает завершения всех подпроцессов.

22-25     Если какой-то из подпроцессов завершается с плохим статусным кодом, то все остальные принудительно завершаются посылкой сигнала SIGTERM. Заметьте, что сигнал посылается также тому процессу, который только что завершился, но это не причиняет вреда. Внутри цикла каждый порождённый процесс ожидается индивидуально, повторяющимися вызовами wait(2).

Эта программа исполняется каждым из подпроцессов. Каждому из них требуется различное время для того, чтобы завершиться. Различное время выполнения изображается вызовом библиотечной функции sleep(3C). sleep(3C) будет описано ниже. Каждый процесс спит случайное количество времени.

Замечание: сначала генератор случайных чисел должен быть инициализирован с использованием srand(3C), после чего rand(3C) выдаёт случайные числа. См. rand(3C) для более детального знакомства.

Рассмотрите выполнение этого примера. Получилось так, что порождённый процесс номер четыре завершился первым, с кодом выхода равным 1 (status равен 256). Поэтому остальные подпроцессы будут завершены сигналом SIGTERM. Заметьте, что здесь печатается неразобранное слово состояния процесса, а не код завершения exit(2).

Это программа, которую исполняют порожденные процессы:

1        #include <stdlib.h>

2        #include <sys/types.h>

3        main()

4        {

5                srand( (unsigned)getpid() );

6

7                /* processing done here */

8                sleep((rand() % 5) + 1);

9                exit(1);

10        }

 

$ parent

parent: waiting for children

child 9725: terminated, status: 256

child 9722: terminated, status: 15

child 9723: terminated, status: 15

child 9724: terminated, status: 15

child 9726: terminated, status: 15

parent: all children terminated

 

Файлы: parent.c и child.c


      ПРИНУДИТЕЛЬНОЕ ЗАВЕРШЕНИЕ ПОДПРОЦЕССОВ - ПРИМЕР

1 #include <sys/types.h>

2 #include <sys/signal.h>

3 #include <sys/procset.h>

4 #include <unistd.h>

5 #include <wait.h>

6 #define NUMCHILD 5

7

8 main(int argc, char **argv)

9 {

10 int i, status;

11 pid_t pid, chpid[NUMCHILD];

12

13 for (i = 0; i < NUMCHILD; i++) {

14     if ((pid = fork()) == 0)

15         execlp("child","child",(char*) 0);

16     chpid[i] = pid;

17    }

18 printf("parent: waiting for children\n");

19 while ((pid = wait(&status)) != -1) {

20     printf("child %d: terminated, status:

21                       %d\n", pid, status);

22     if (WEXITSTATUS(status) != 0) {

23          for (i = 0; i < NUMCHILD; i++)

24                sigsend(P_PID, chpid[i], SI

25     }

26 }

27 printf("parent: all children terinated\n")

28

29 exit(0);

30 }

 

Воздействие сигнала на ввод

Этот пример показывает результат получения сигнала во время чтения с терминала.

12-13     Если сигнал игнорировался, то действие по прежнему будет состоять в игнорировании сигнала.

14-24     Этот цикл читает строки со стандартного ввода и пишет их на стандартный вывод.

14-19         Если read(2)  завершается неудачно из-за получения сигнала, исполнение продолжается с начала цикла. Иначе цикл завершается, потому что достигнут настоящий конец файла.

Ниже показано, как работает этот пример. Необходимо выполнять демонстрацию из под командной оболочки /bin/sh, чтобы гарантировать, что все процессы принадлежат к одной группе. Сначала в фоновом режиме запускается команда, которая спит, а потом посылает сигнала SIGINT (сигнал номер 2) всем процессам в группе, управляемой TTY.

Замечание: Интерпретатор shell получает сигнал прерывания, но игнорирует его.

Затем, сигнал прибывает во время печатания букв X. Эти буквы должны быть прочитаны строкой 18 программы. Заметьте, что ввод из-за сигнала не теряется.

$ sh

$ (sleep 5; kill -2 0) &

19952

$ input

XXXXXsignal 2 received

XX

n: 8

XXXXXXX

<CTRL d>

 

Файл: input.c


                ВОЗДЕЙСТВИЕ СИГНАЛА НА ВВОД

1 #include <stdio.h>

2 #include <signal.h>

3 #include <errno.h>

4 #include <stdlib.h>

5

6 main()

7 {

8 void sigcatch(int);

9 char buf[BUFSIZ];

10 int n;

11

12 signal(SIGINT, sigcatch);

13

14 for (;;) {

15  if ((n = read(0, buf, BUFSIZ)) <= 0) {

16      if (errno == EINTR) {

17         errno = 0;

18         continue;

19      }

20      break;

21  }

22  printf("n: %d\n", n);

23  write(1, buf, n);

24 }

25 exit(0);

26 }

27

28 void sigcatch(int sig)

29 {

30 signal(SIGINT, SIG_IGN);

31 printf("signal %d received\n", sig);

32 signal(SIGINT, sigcatch);

33 }

 

Будильник (alarm clock)

Системный вызов alarm(2) используется для того, чтобы установить будильник для процесса, который исполнил этот вызов. Через sec секунд после вызова alarm, ядро генерирует сигнал SIGALRM и посылает его этому процессу.

Одно из использований alarm(2) — установка предела времени для системных вызовов, которые могут слишком долго исполняться. Например, сигнал SIGALRM может прервать read(2), который не получает никакого ввода с терминала.

В каждый момент в одном процессе может существовать только одна установка будильника. Если следующий системный вызов alarm(2) будет исполнен до того, как истечет время, установленное предыдущим вызовом, новый вызов возвратит количество времени, оставшееся от первой установки (0, если ничего не было установлено), и будильник приобретет новое значение. Если задано 0 секунд, будильник будет выключен.

 


Дата добавления: 2018-06-27; просмотров: 212; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!