Linux программирование в примерах
Шрифт:
Или предположим, что вы используете
Оба случая относятся к состоянию гонки. Одним решением для этих проблем является как можно большее упрощение обработчиков сигналов. Это можно сделать, создав флаговые переменные, указывающие на появление сигнала. Обработчик сигнала устанавливает переменную в true и возвращается. Затем основная логика проверяет флаговую переменную в стратегических местах:
(Обратите внимание, что эта стратегия уменьшает окно уязвимости, но не устраняет его).
Стандарт С вводит специальный тип —
Наличие особого типа является лишь частью истории. Переменные
Ключевое слово
Структурирование приложения исключительно вокруг переменных
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.
Наша история до настоящего времени, эпизод 1Сигналы являются сложной темой, и она становится еще более сбивающей с толку. Поэтому давайте на время сделаем остановку, сделаем шаг назад и подведем итог обсужденному до сих пор:
• Сигналы являются указанием того, что произошло некоторое внешнее событие.
•
•
• Когда сигнал перехватывается, вызывается функция-обработчик. Вот где сложность начинает поднимать свою безобразную голову:
• ISO С не определяет, восстанавливается ли диспозиция сигнала по умолчанию до вызова обработчика или она остается на месте. Первое является поведением V7 и современных систем System V, таких, как Solaris. Последнее является поведением BSD, используемым также в GNU/Linux. (Для форсирования поведения BSD может использоваться функция POSIX
• То, что случается при прерывании сигналом системного вызова, также различается в традиционной и BSD линейках. Традиционные системы возвращают -1 с errno, установленным в
POSIX требует, чтобы частично выполненный системный вызов возвращал успешное завершение, указав, сколько работы было выполнено. Системный вызов, который еще не начал выполняться, вызывается повторно.
• Механизм
• Применяется ряд дополнительных предостережений, и в частности, из обработчика сигнала безопасно может вызываться лишь часть стандартных библиотечных функций.
Несмотря на эти проблемы интерфейса