В системах, в которых задействуется реализация потоков LinuxThreads, константа SIGRTMIN определена со значением 35 (а не 32), потому что в технологии LinuxThreads первые три сигнала реального времени применяются для внутренних целей. В системах, в которых задействуется реализация потоков NPTL, константа SIGRTMIN определена со значением 34, так как в технологии NPTL первые два сигнала реального времени применяются для внутренних целей.

В отличие от стандартных сигналы реального времени не определяются отдельными константами. Однако не стоит использовать в коде программы непосредственно целочисленные значения номеров сигналов, так как диапазон номеров в различных реализациях UNIX отличается. Вместо этого сигнал реального времени может быть обозначен с помощью прибавления значения к константе SIGRTMIN, так выражение (SIGRTMIN+1) ссылается на второй сигнал реального времени.

Обратите внимание, что стандарт SUSv3 не требует, чтобы значения констант SIGRTMIN и SIGRTMAX были представлены обычными целыми числами. Значения этих констант могут быть определены как функции (как это происходит в Linux). А это значит, что мы не можем написать для препроцессора код, аналогичный следующему:

#if SIGRTMIN+100 > SIGRTMAX /* НЕПРАВИЛЬНО! */

#error "Not enough realtime signals"

#endif

Вместо этого мы должны осуществить эквивалентные проверки во время выполнения.

Ограничения количества сигналов реального времени в очереди

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

В этом случае стандарт SUSv3 позволяет реализации устанавливать верхний предел количества сигналов в очереди, а также требует, чтобы это количество как минимум равнялось _POSIX_SIGQUEUE_MAX (константа определена со значением 32). В реализации может быть определена константа SIGQUEUE_MAX, показывающая наибольшее количество сигналов реального времени, которые могут быть поставлены в очередь. Данная информация может быть доступна посредством осуществления следующего вызова:

lim = sysconf(_SC_SIGQUEUE_MAX);

В Linux данный вызов возвращает значение –1. Причина кроется в том, что в Linux реализована иная модель ограничения количества сигналов реального времени, которые могут быть поставлены в очередь процесса. В Linux версий до 2.6.7 включительно ядро требовало установки ограничения уровня системы для общего количества сигналов реального времени, которые могут быть поставлены в очереди всех процессов. Это ограничение может быть просмотрено и (при наличии привилегий) изменено в специфичном файле Linux /proc/sys/kernel/rtsig-max. По умолчанию значение в этом файле равно 1024. Количество сигналов, находящихся в очереди в данный момент, можно просмотреть в характерном для Linux файле /proc/sys/kernel/rtsig-nr.

Начиная с Linux 2.6.8, эта модель была изменена, а вышеупомянутые интерфейсы /proc — удалены. По новой модели константа RLIMIT_SIGPENDING устанавливает мягкое ресурсное ограничение на количество сигналов, которые могут быть поставлены в очереди всех процессов конкретного реального ID пользователя. Более подробное описание этого ограничения приводятся в разделе 36.3.

Использование сигналов реального времени

Для того чтобы пара процессов могла отправить и получить сигналы реального времени, стандарт SUSv3 требует следующее.

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

Сигнал реального времени также может быть послан с помощью функций kill(), killpg() и raise(). Однако стандарт SUSv3 оставляет авторам реализации решать, возможна ли постановка в очередь сигналов реального времени, отправляемых с помощью вышеперечисленных интерфейсов. Так, в Linux эти интерфейсы могут использоваться для постановки сигналов в очередь, однако во многих других реализациях UNIX — нет.

• Процесс, получающий сигнал, устанавливает обработчик для этого сигнала с помощью вызова функции sigaction(), в которой указывается флаг SA_SIGINFO. Этот флаг приводит к инициализации обработчика сигнала с дополнительными аргументами, один из которых включает данные, сопровождающие сигнал.

В Linux есть возможность поставить в очередь сигнал реального времени, даже если процесс, получающий сигнал, не указал флаг SA_SIGINFO при установке обработчика (однако в данном случае будет невозможно получить данные, связанные с сигналом). Однако стандарт SUSv3 не обязывает реализации гарантировать такое поведение, следовательно, мы не можем полагаться на наличие такой возможности.

22.8.1. Отправка сигналов реального времени

Перейти на страницу:

Похожие книги