Материал: 6262

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

 

136

 

Подразумеваемая реакция - аварийное завершение и создание

 

файла с образом памяти процесса.

SIGSTOP

Остановка выполнения (этот сигнал нельзя перехватить для

 

обработки или проигнорировать).

 

Подразумеваемая реакция - остановка процесса.

SIGTERM

Сигнал терминирования.

 

Подразумеваемая реакция - аварийное завершение процесса.

SIGTSTP

Сигнал остановки, поступивший с терминала.

 

Подразумеваемая реакция - остановка процесса.

SIGTTIN

Попытка чтения из фонового процесса.

 

Подразумеваемая реакция - остановка процесса.

SIGTTOU

Попытка записи из фонового процесса.

 

Подразумеваемая реакция - остановка процесса.

SIGUSR1,

Определяемые пользователем сигналы.

SIGUSR2

Подразумеваемая реакция - аварийное завершение процесса.

SIGPOLL

Опрашиваемое событие.

 

Подразумеваемая реакция - аварийное завершение процесса.

SIGPROF

Срабатывание таймера профилирования.

 

Подразумеваемая реакция - аварийное завершение процесса.

SIGSYS

Некорректный системный вызов.

 

Подразумеваемая реакция - аварийное завершение и создание

 

файла с образом памяти процесса.

SIGTRAP

Попадание в точку трассировки/прерывания.

 

Подразумеваемая реакция - аварийное завершение и создание

 

файла с образом памяти процесса.

SIGURG

Высокоскоростное поступление данных в сокет.

 

Подразумеваемая реакция - игнорирование.

SIGVTALRM

Срабатывание виртуального таймера.

 

Подразумеваемая реакция - аварийное завершение процесса.

SIGXCPU

Исчерпан лимит процессорного времени.

 

Подразумеваемая реакция - аварийное завершение и создание

 

файла с образом памяти процесса.

SIGXFSZ

Превышено ограничение на размер файлов.

 

Подразумеваемая реакция - аварийное завершение и создание

 

файла с образом памяти процесса.

В целом, технология использования сигналов достаточно сложна и требует знания многих аспектов работы ОС.

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

137

завершения.

Если остановка дочернего процесса вызвана получением соответствующего сигнала, то родительский процесс может узнать об этом с помощью системного вызова waitpid(...).

На листинге 3.7 представлена программа, в которой:

родительский процесс, в цикле, создает пять дочерних процессов, после чего начинает ожидать их завершение, отслеживая остановки по получению сигналов;

каждый дочерний процесс, после небольшого тайм-аута, посылает себе сигнал SIGSTOP, останавливая свою работу;

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

Листринг 3.7 — Пример перезапуска дочерних процессов, остановленных сигналом

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

int main(void) {

puts("Проект lab9.7 ..."); pid_t pid, cpid;

int i, status=0xAAAA;

puts("Запуск пяти дочерних процессов:"); for (i=0; i<5; i++) {

pid = fork(); if (pid > 0) {

printf(" Родителский процесс: Запустил ДП%i с pid = %i\n", i, pid);

}else{

sleep(i + 3);

printf(" ДП%i pid=%i: останавливаюсь сигналом SIGTOP\n", i, getpid()); raise(SIGSTOP);

printf(" ДП%i: Завершаюсь со статусом = %i\n", i, i); exit(i);

}

}

sleep(1);

puts("Ожидание завершения дочерних процессов:"); while((cpid = waitpid(-1, &status, WUNTRACED)) > 0) {

if (WIFSTOPPED(status)) {

printf(" РП: процесс pid = %i остановлен сигналом = %i\n", cpid, WSTOPSIG(status));

sleep(1);

printf(" РП: посылаю сигнал SIGCONT процессу pid = %i\n", cpid); kill(cpid, SIGCONT);

}

if (WIFEXITED(status)) {

printf(" РП: процесс pid = %i завершился со статусом = %i\n", cpid, WEXITSTATUS(status));

}

}

puts("Завершение проекта lab9.7 ..."); return EXIT_SUCCESS;

}

138 Пример запуска этой программы представлен на рисунке 3.7.

Рисунок 3.7 — Посылка сигналов дочерним процессам

В приложениях так же часто используются системные вызовы, останавливающие выполнение процесса. К ним относятся:

#include <unistd.h>

unsigned int sleep(unsigned int seconds); int pause(void);

где seconds — число секунд, на которое процесс «засыпает».

Эти вызовы не посылают родительскому процессу сигналов, но сами реагируют на сигнал SIGCONT. Поэтому, когда они блокируют выполнение программы, родительский процесс может снять их действие по тайм-ауту, посылая сигнал.

139 На листинге 3.8 представлена программа, в которой:

родительский процесс, в цикле, создает пять дочерних процессов, после чего «засыпает» на 5 секунд, а затем посылает всем дочерним процессам сигнал

SIGCONT;

все дочерние процессы регистрируют обработчик сигнала SIGCONT;

первые два дочерних процесса останавливают свою работу с помощью системного вызова pause(...);

остальные дочерние процессы останавливают свою работу с помощью системного вызова sleep(…).

Листринг 3.8 — Пример перезапуска дочерних процессов по тайм-ауту

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

int np = 0;

 

// Номер дочернего процесса

 

void handler(int sig){

// Обработчик сигнала

 

printf("

ДП%i pid=%i: получил сигнал %i\n", np, getpid(), sig);

 

}

 

 

 

int main(void) {

 

 

puts("Проект lab9.8 ...");

 

pid_t pid, cpid;

 

 

int i, status=0xAAAA;

 

puts("Запуск пяти дочерних процессов:");

 

for (i=0; i<5; i++) {

 

pid = fork();

 

if (pid > 0) {

 

 

printf("

Родителский процесс: Запустил ДП%i с pid = %i\n",

i, pid);

}else{

// Дочерние процессы

 

 

np = i;

 

 

 

signal(SIGCONT, handler); // Регистрирую обработчик сигнала SIGCONT

if (i < 3){

printf("

ДП%i pid=%i: останавливаюсь pause()...\n", i, getpid());

pause();

 

 

}else{

 

 

printf("

ДП%i pid=%i: останавливаюсь sleep(100)\n",

i, getpid());

sleep(100);

 

}

 

 

printf("

ДП%i pid=%i: Завершаюсь со статусом = %i\n", i, getpid(), i);

exit(i);

 

 

}

}

puts("Ожидание завершения дочерних процессов:"); sleep(5);

if (kill(0, SIGCONT) < 0){ // Посылаю сигнал всем, входящим в мою группу perror("kill():");

}

while((cpid = waitpid(-1, &status, WUNTRACED)) > 0) { if (WIFSTOPPED(status)) {

printf(" РП: процесс pid = %i остановлен сигналом = %i\n", cpid, WSTOPSIG(status));

sleep(1);

printf(" РП: посылаю сигнал SIGCONT процессу pid = %i\n", cpid); kill(cpid, SIGCONT);

}

140

if (WIFEXITED(status)) {

printf(" РП: процесс pid = %i завершился со статусом = %i\n", cpid, WEXITSTATUS(status));

}

}

puts("Завершение проекта lab9.8 ..."); return EXIT_SUCCESS;

}

На рисунке 3.8 показан результат работы этой программы.

Рисунок 3.8 — Пробуждение процессов обработчиком сигналов

Источник: https://studfile.net/preview/16438530/