В случае с терминалами и псевдотерминалами сигнал генерируется в момент, когда становится доступным новый ввод, даже если предыдущий ввод еще не был прочитан. Сигнал о возможности ввода также передается при обнаружении конца файла (только для терминала).
Терминалы не получают сигналы о возможности вывода и разрыве соединения.
С версии ядра 2.4.19 Linux передает сигнал о возможности вывода вторичному псевдотерминалу. Он генерируется всякий раз, когда ввод принимается на первичной стороне.
Именованные каналы и очереди FIFO
Для считывающего конца именованного канала или очереди FIFO сигнал генерируется в следующих ситуациях:
• данные записаны в канал (даже если там уже находится непрочитанный ввод);
• записывающий конец канала закрыт.
Для записывающего конца именованного канала или очереди FIFO сигнал генерируется в следующих ситуациях:
• чтение из канала увеличивает объем свободного пространства в нем, благодаря чему становится возможным записать без блокировки PIPE_BUF байтов;
• считывающий конец канала закрыт.
Сокеты
Ввод/вывод на основе сигналов поддерживает датаграммные сокеты в UNIX- и интернет-доменах. Сигнал генерируется в следующих ситуациях:
• в сокет поступает входящая датаграмма (даже если в очереди находятся другие непрочитанные датаграммы);
• в сокете происходит асинхронная ошибка.
Ввод/вывод на основе сигналов работает также и для потоковых сокетов в обоих доменах. Сигнал генерируется в следующих ситуациях:
• слушающий сокет принял новое соединение;
• завершается TCP-запрос connect(); то есть активный конец TCP-соединения входит в состояние ESTABLISHED (см. рис. 57.5). Условие не срабатывает для сокетов в домене UNIX;
• сокет принял новый ввод (даже если в нем уже доступны непрочитанные данные);
• удаленная сторона закрывает свою записывающую часть соединения с помощью вызова shutdown() или все соединение целиком, используя вызов close();
• становится возможным вывод из сокета (например, когда освобождается место в его исходящем буфере);
• в сокете происходит асинхронная ошибка.
Файловые дескрипторы inotify
Сигнал генерируется, когда становится доступным файловый дескриптор inotify, то есть если с любым из файлов, которые он отслеживает, происходит какое-то событие.
59.3.3. Эффективное использование ввода/вывода на основе сигналов
В приложениях, которым нужно наблюдать за большим количеством (то есть тысячами) файловых дескрипторов (например, отдельными видами сетевых серверов), ввод/вывод на основе сигналов может обеспечить значительное увеличение производительности по сравнению с вызовами select() и poll(). Дело в том, что ядро «запоминает» список отслеживаемых дескрипторов и оповещает программу только в момент, когда с ними происходят события ввода/вывода. Таким образом, производительность программы, применяющей ввод/вывод на основе сигналов, масштабируется в зависимости от количества событий, а не подконтрольных файловых дескрипторов.
Чтобы применять весь потенциал этой методики, нужно выполнить два шага:
• воспользоваться вызовом fcntl() с флагом F_SETSIG (поддерживается только в Linux) с целью указать сигнал реального времени, который должен быть доставлен вместо SIGIO, когда станет возможным ввод/вывод для заданного файлового дескриптора;
• указать флаг при использовании вызова sigaction(), чтобы установить обработчик сигнала реального времени, указанного в предыдущем шаге (см. раздел 21.4).
Операция fcntl() F_SETSIG позволяет указать альтернативный сигнал, который должен быть доставлен вместо SIGIO как оповещение о возможности ввода/вывода для файлового дескриптора:
if (fcntl(fd, F_SETSIG, sig) == -1)
errExit("fcntl");
F_GETSIG выполняет действие, обратное операции F_SETSIG: извлекает сигнал, установленный на данный момент для файлового дескриптора:
sig = fcntl(fd, F_GETSIG);
if (sig == -1)
errExit("fcntl");
Для того чтобы получить определения констант F_SETSIG и F_GETSIG из заголовочного файла
Флаг F_SETSIG для изменения сигнала, оповещающего о возможности ввода/вывода, служит двум целям, каждая из которых является обязательной при мониторинге большого количества событий ввода/вывода для множества файловых дескрипторов.
• По умолчанию для оповещения о возможности ввода/вывода применяется стандартный сигнал SIGIO, который минует очередь. Если события начнут поступать в момент, когда этот сигнал заблокирован (возможно, его обработчик уже вызван), то все они, кроме первого, будут утеряны. При использовании вместо SIGIO сигнала реального времени F_SETSIG уведомления будут складываться в очередь.