Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
практична робота 8.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
232.96 Кб
Скачать

Поняття про надійність сигналів. Posix функції для роботи з сигналами

Основним недоліком системного виклику signal() є його низька надійність.

В багатьох варіантах операційної системи UNIX встановлена при його допомозі обробка сигналу призначеною для користувача функцією виконується тільки один раз, після чого автоматично відновлюється реакція на сигнал за умовчанням. Для постійної призначеної для користувача обробки сигналу необхідно кожного разу наново встановлювати реакцію на сигнал прямо усередині функції-обробника.

В системних викликах і призначених для користувача програмах можуть існувати критичні ділянки, на яких процесу неприпустимо відволікатися на обробку сигналів. Ми можемо виставити на цих ділянках реакцію "ігнорувати сигнал" з подальшим відновленням попередньої реакції, але якщо сигнал все-таки виникне на критичній ділянці, то інформація про його виникнення буде безповоротно втрачена.

Нарешті, останній недолік пов'язаний з неможливістю визначення кількості сигналів одного і того ж типу, що поступили процесу, поки він знаходився в змозі готовність. Сигнали одного типу в чергу не ставляться! Процес може дізнатися про те, що сигнал або сигнали певного типу були йому передані, але не може визначити їх кількість. Цей недолік ми можемо проілюструвати, злегка змінивши програму з асинхронним отриманням інформації про статус процесів, що завершилися, розглянуту нами раніше в розділі "Вивчення особливостей отримання термінальних сигналів поточною і фоновою групою процесів". Хай в новій програмі 13–14-6.c процес-батько породжує в циклі п'ять нових процесів, кожний з яких зразу ж завершується з своїм власним кодом, після чого йде в нескінченний цикл.

/* Програма для ілюстрації ненадійності сигналів */

#include <sys/types.h>

#include <unistd.h>

#include <waith>

#include <signal.h>

#include <stdio.h>

/* Функція my_handler – обробник сигналу SIGCHLD */

void my_handler(int nsig){

int status;

pid_t pid;

/* Опитуємо статус процесу, що завершився, і одночасно взнаємо його ідентифікатор */

if((pid = waitpid(-1 &status, 0)) < 0){

/* Якщо виникла помилка – повідомляємо про неї і продовжуємо роботу */

printf("Some error on waitpid errno = %d\n", errno);

} else {

/* Інакше аналізуємо статус процесу, що завершився */

if ((status & 0xff) == 0) {

/* Процес завершився з явним або неявним викликом функції exit() */

printf("Process %d was exited with status %d\n", pid, status >> 8);

} else if ((status & 0xff00) == 0){

/* Процес був завершений за допомогою сигналу */

printf("Process %d killed signal %d %s\n", pid, status &0x7f,(status & 0x80)? "with core file" : "without core file");

}

}

}

int main(void){

pid_t pid;

int i;

/* Встановлюємо обробник для сигналу SIGCHLD */

(void) signal(SIGCHLD, my_handler);

/* В циклі породжуємо 5 процесів-дітей */

for (i=0; i

if((pid = fork()) < 0){

printf("Can\'t fork child %d\n", i);

exit(1);

} else if (pid == 0){

/* Child i – завершується з кодом 200 + i */

exit(200 + i);

}

/* Продовження процесу-батька – йдемо на нову ітерацію */

}

/* Продовження процесу-батька – йдемо в цикл */

while(1);

return 0;

}

Лістинг 13-14.6. Програма (13–14-6.c) для ілюстрації ненадійності сигналів.

Подальші версії System V і BSD намагалися усунути ці недоліки власними засобами. Єдиний спосіб більш надійної обробки сигналів з'явився з введенням POSIX стандарту на системні виклики UNIX. Набір функцій і системних викликів для роботи з сигналами був істотно розширений і побудований таким чином, що дозволяв тимчасово блокувати обробку певних сигналів, не допускаючи їх втрати. Проте проблема, пов'язана з визначенням кількості сигналів одного типу, що прийшли, як і раніше залишається актуальною. (Треба відзначити, що подібна проблема існує на апаратному рівні і для зовнішніх переривань. Процесор часто не може визначити, яка кількість зовнішніх переривань з одним номером виникла, поки він виконував чергову команду.)