12.4. Написание обработчиков сигналов

12.4. Написание обработчиков сигналов

Хотя обработчик сигнала выглядит подобно обычной функции С, он не вызывается так, как она. Вместо того чтобы быть частью нормальной последовательности вызовов программы, обработчик вызывается ядром. Ключевое различие между этими двумя вещами заключается в том, что обработчик может быть вызван почти в любое время, даже во время выполнения отдельного оператора С! Есть только несколько ограничений того, когда система может вызвать обработчик сигнала, на который вы полагаетесь.

1. Семантика некоторых сигналов ограничивает, когда они могут быть посланы. Так, например, SIGCHLD обычно посылается программам, у которых нет дочерних процессов[65]. Большинство сигналов, подобных SIGHUP, посылаются в непредсказуемые моменты.

2. Если процесс находится в процессе обработки некоторого сигнала, то обработчик сигнала не вызывается повторно для обработки того же сигнала, если только не была задана опция SA_NODEFER. Процесс также может блокировать дополнительные сигналы, если сигнал, который обрабатывается, указан в члене sa_mask структуры struct sigaction.

3. Процесс может блокировать сигналы, когда выполняется часть кода, используя sigprocmask(). Ранее в этой главе был дан пример использования этого средства для обеспечения атомарного обновления структур данных.

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

Одним из наиболее важных моментов, за которым нужно следить, является модификация глобальных данных. Если только не делать этого аккуратно, возможно получение ситуации состязаний. Простейший способ обеспечить безопасность обновления глобальных данных — просто избегать его. Второй, и лучший, способ — это блокировка всех обработчиков сигналов, которые модифицируют определенные структуры данных, всякий раз, когда остальная часть кода модифицирует их, с тем, чтобы обеспечить одновременное манипулирование этими данными только одним сегментом кода одновременно.

Хотя обработчик сигнала может читать структуры данных, когда его прерывает другой читатель этих данных, все прочие комбинации являются небезопасными. Более безопасно обработчику сигнала модифицировать структуры данных, которые читает остальная часть программы, чем наоборот — обработчику сигналов читать структуры данных, которые остальная часть программы выполняет запись. Некоторые специализированные структуры данных спроектированы так, чтобы позволить параллельный доступ, но их описание выходит за круг тем, рассматриваемых в настоящей книге.

Если вам требуется доступ к глобальным данным из обработчика сигналов (что и делает большинство обработчиков), оставляйте структуры данных простыми. Хотя достаточно просто безопасно модифицировать отдельный элемент данных, такой как int, более сложные структуры обычно требуют блокировки сигналов. Любые глобальные переменные, которые могут быть модифицированы обработчиками сигналов, должны быть объявлены с ключевым словом volatile. Это сообщает компилятору, что переменная может быть изменена вне нормального потока программы, и он не должен пытаться оптимизировать доступ к этой переменной.

Другая вещь, с которой нужно соблюдать осторожность в обработчиках сигналов — это вызов других функций, потому что они тоже могут изменять глобальные данные! Библиотека С stdio пытается облегчить это и не допускает вызовов своих функций из обработчиков сигналов. В табл. 12.2 перечислены функции, которые гарантированно являются безопасными для вызова из обработчиков сигналов[66]; вызовов всех прочих функций следует избегать.

Таблица 12.2. Реентерабельные функции

abort() accept() access()
aio_error() aio_return() aio_suspend()
alarm() bind() cfgetispeed()
cfgetospeed() cfsetispeed() cfsetospeed()
chdir() chmod() chown()
close() connect() creat()
dup() dup2() execle()
execve() _exit() fchmod()
fchown() fcntl() fdatasync()
fork() fpathconf() fstat()
fsync() getegid() geteuid()
getgid() getgroups() getpeername()
getpgrp() getpid() getppid()
getuid() kill() link()
listen() lseek() lstat()
mkdir() mkfifo() open()
pathconf() pause() pipe()
poll() posix_trace_event() pselect()
raise() read() readlink()
recv() recvfrom() recvmsg()
rename() rmdir() select()
sem_post() send() sendmsg()
sendto() setgid() setpgid()
setsid() setsockopt() setuid()
shutdown() sigaction() sigaddset()
sigdelset() sigemptyset() sigfillset()
sigismember() signal() sigpause()
sigpending() sigprocmask() sigqueue()
sigset() sigsuspend() sleep()
socket() socketpair() stat()
symlink() sysconf() tcdrain()
tcflow() tcflush() tcgetattr()
tcgetpgrp() tcsendbreak() tcsetattr()
tcsetpgrp() time() timer_getoverrun()
timer_gettime() timer_settime() times()
umask() uname() unlink()
utime() wait() wait3()
wait4() waitpid() write()
Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

7.2.1 Обработка сигналов

Из книги Архитектура операционной системы UNIX автора Бах Морис Дж

7.2.1 Обработка сигналов Ядро обрабатывает сигналы в контексте того процесса, который получает их, поэтому чтобы обработать сигналы, нужно запустить процесс. Существует три способа обработки сигналов: процесс завершается по получении сигнала, не обращает внимание на


Пример: использование обработчиков завершения для повышения качества программ

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Пример: использование обработчиков завершения для повышения качества программ Обработчики исключений и завершения позволяют повысить надежность программ как за счет упрощения процедуры восстановления программы после возникновения ошибок и исключений, так и за счет


Обзор обработчиков

Из книги Справочник по PHP автора

Обзор обработчиков handler_openЭтот обработчик должен взять на себя всю работу по открытию базы данных для группы сессий с именем, которое было передано ей в параметрах.Синтаксис:bool handler_open(string $save_path, string $session_name)Функция вызывается, когда вызывается session_start(). Обработчик должен


Привязка и удаление обработчиков событий

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов. автора Дронов Владимир

Привязка и удаление обработчиков событий Метод on объекта Element выполняет привязку указанной функции к указанному событию данного элемента Web-страницы в качестве обработчика:<экземпляр объекта Element>.on(<событие>, <функция-обработчик>)Первым параметром методу


Привязка и удаление обработчиков событий

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов автора Дронов Владимир

Привязка и удаление обработчиков событий Метод on объекта Element выполняет привязку указанной функции к указанному событию данного элемента Web-страницы в качестве обработчика:<экземпляр объекта Element>.on(<событие>, <функция-обработчик>)Первым параметром методу


12.1. Концепция сигналов

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

12.1. Концепция сигналов 12.1.1. Жизненный цикл сигнала Сигналы имеют четко определенный жизненный цикл: они создаются, сохраняются до тех пор, пока ядро не выполнит определенное действие на основе сигнала, а затем вызывают совершение этого действия. Создание сигнала


12.2.1. Посылка сигналов

Из книги Linux: Полное руководство автора Колисниченко Денис Николаевич

12.2.1. Посылка сигналов Посылка сигналов от одного процесса другому обычно осуществляется с помощью системного вызова kill(). Этот системный вызов подробно обсуждался в главе 10. Вариантом kill() является tkill(), который не предназначен для прямого использования в программах.int


12.2.3. Перехват сигналов

Из книги Macromedia Flash Professional 8. Графика и анимация автора Дронов В. А.

12.2.3. Перехват сигналов Вместо использования функции signal() (чья семантика в процессе эволюции стала неправильной) POSIX-программы регистрируют обработчики сигналов с помощью sigaction().#include <signal.h>int sigaction(int signum, struct sigaction *act, struct sigaction *oact);Этот системный вызов устанавливает


23.3.4. Обработка сигналов

Из книги Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform автора Кёртен Роб

23.3.4. Обработка сигналов Перед тем, как перейти к следующему пункту, нужно еще раз рассмотреть функцию gtk_signal_connect(). Данной функции нужно передать четыре параметра:? GtkObject *object — объект, которому может быть послан сигнал;? const gchar *name — имя сигнала, например, «destroy»;? GtkSignalFunc func


Написание сценария

Из книги Графология XXI века автора Щеголев Илья Владимирович

Написание сценария Итак, с панелью Actions мы вкратце познакомились. Конечно, полностью ее возможности (кстати, весьма широкие) мы не рассмотрели, но сейчас нам важнее написать наш первый сценарий, чем выяснять, чем богата эта панель. Позже мы займемся ей более подробно.Выше


Написание обработчиков прерываний

Из книги QT 4: программирование GUI на С++ автора Бланшет Жасмин

Написание обработчиков прерываний Давайте посмотрим, как настроить обработчики прерываний — вызовы, характеристики и кое-какие стратегии


Подключение обработчиков прерываний

Из книги Идеальный программист. Как стать профессионалом разработки ПО автора Мартин Роберт С.

Подключение обработчиков прерываний Для подключения к источнику прерывания воспользуйтесь функцией InterruptAttach() или InterruptAttachEvent().#include <sys/neutrino.h>int InterruptAttachEvent(int intr, const struct sigevent *event, unsigned flags);int InterruptAttach(int intr, const struct sigevent* (*handler)(void *area, int id), const void *area, int size, unsigned flags);Параметр


Написание букв

Из книги автора

Написание букв Окно программы содержит две вкладки: «Написание букв» и «Графологический анализ».Щелкнув на вкладке «Написание букв», вы попадаете в раздел для определения сильных и слабых качественных черт характера по форме написания букв (рис. 199). Рис. 199Слева


4 Написание кода

Из книги автора

4 Написание кода В предыдущей книге[13] я подробно описал структуру и природу Чистого Кода. В этой главе будет рассмотрен сам акт написания кода, а также контекст, в котором он происходит.Когда мне было 18 лет, я набирал текст достаточно быстро, но мне приходилось смотреть на