Linux программирование в примерах
Шрифт:
10.4.5. Состояния гонок и
Пока обработка одного сигнала за раз выглядит просто: установка обработчика сигнала в
Но что произойдет, если возникнут два идентичных сигнала, один за другим? В частности, что, если ваша система восстановит действие по умолчанию для вашего сигнала, а второй сигнал появится после вызова обработчика, но до того, как он себя восстановит?
Или предположим, что вы используете
Оба случая относятся к состоянию гонки. Одним решением для этих проблем является как можно большее упрощение обработчиков сигналов. Это можно сделать, создав флаговые переменные, указывающие на появление сигнала. Обработчик сигнала
(Обратите внимание, что эта стратегия уменьшает окно уязвимости, но не устраняет его).
Стандарт С вводит специальный тип —
Наличие особого типа является лишь частью истории. Переменные
Ключевое слово
Структурирование приложения исключительно вокруг переменных
10.4.6. Дополнительные предостережения
Стандарт POSIX предусматривает для обработчиков сигналов несколько предостережений:
• Что случается, когда возвращаются обработчики для
• Если обработчик был вызван в результате вызова
• Обработчики сигналов могут вызвать лишь функции из табл. 10.2. В частности, они должны избегать функций
Список в табл. 10.2 происходит из раздела 2.4 тома System Interfaces (Системные интерфейсы) стандарта POSIX 2001. Многие из этих функций относятся к сложному API и больше не рассматриваются в данной книге.
Таблица 10.2. Функции, которые могут быть вызваны из обработчика сигнала
| _Exit | fpathconf | raise | sigqueue |
| _exit | fstat | read | sigset |
| accept | fsync | readlink | sigsuspend |
| access | ftruncate | recv | sleep |
| aio_error | getegid | recvfrom | socket |
| aio_return | geteuid | recvmsg | socketpair |
| aio_suspend | getgid | rename | stat |
| alarm | getgroups | rmdir | sysmlink |
| bind | getpeername | select | sysconf |
| cfgetispeed | getpgrp | sem_post | tcdrain |
| cfgetospeed | getpid | send | tcflow |
| cfsetispeed | getppid | sendmsg | tcflush |
| cfsetospeed | getsockname | sendto | tcgetattr |
| chdir | getsockopt | setgid | tcgetpgrp |
| chmod | getuid | setpgid | tcsendbreak |
| chown | kill | setsid | tcsetattr |
| clock_gettime | link | setsockopt | tcsetpgrp |
| close | listen | setuid | time |
| connect | lseek | shutdown | timer_getoverrun |
| creat | lstat | sigaction | timer_gettime |
| dup | mkdir | sigaddset | timer_settime |
| dup2 | mkfifo | sigdelset | times |
| execle | open | sigemptyset | umask |
| execve | pathconf | sigfillset | uname |
| fchmod | pause | sigismember | unlink |
| fchown | pipe | signal | utime |
| fcntl | poll | sigpause | wait |
| fdatasync | posix_trace_event | sigpending | waitpid |
| fork | pselect | sigprocmask | write |
10.4.7.
Сигналы являются сложной темой, и она становится еще более сбивающей с толку. Поэтому давайте на время сделаем остановку, сделаем шаг назад и подведем итог обсужденному до сих пор:
• Сигналы являются указанием того, что произошло некоторое внешнее событие.
•
•
• Когда сигнал перехватывается, вызывается функция-обработчик. Вот где сложность начинает поднимать свою безобразную голову:
• ISO С не определяет, восстанавливается ли диспозиция сигнала по умолчанию до вызова обработчика или она остается на месте. Первое является поведением V7 и современных систем System V, таких, как Solaris. Последнее является поведением BSD, используемым также в GNU/Linux. (Для форсирования поведения BSD может использоваться функция POSIX