Ядро Linux в комментариях

       

Dequeue_signal


Функция dequeue_signal изымает сигнал из сигнальной очереди процесса, пропуская те сигналы, которые определены mask. Функция возвращает номер сигнала и соответствующую siginfo_t через указатель info.

Установка нескольких псевдонимов во избежание повторных разыменований: s — это набор ожидающих сигналов для процесса (помните, что некоторые из них могут быть также и заблокированными), a m — маскирующий набор. В частности, выражение *s, несколько раз встречающееся в функции, — ни что иное как ускоренная версия current->signal.sig[0].

Внутри этого оператора switch значение sig устанавливается равным первому ожидающему сигналу. Этот простейший случай проще всего доступен для понимания; остальные случаи представляют собой лишь его обобщения.

Вот он простейший случай: поразрядная операция И между набором ожидающих сигналов и проинвертированной маской, после чего результат сохраняется во временной переменной х; теперь х представляет собой набор ожидающих сигналов, непроигнорированных маской. Если х не равно 0, значит, такой ожидающий сигнал существует (х содержит, по крайней мере, один установленный разряд); dequeue_signal получает соответствующий номер сигнала с использованием ffz (в книге не рассматривается) и приводит его к нумерации, начиная с 1. Результат сохраняется в sig. Как уже упоминалось, другие случаи являются просто обобщениями данного; важно только то, что в каждом из них sig получает набор — состояние же прочих переменных (i, s, m и х) с этого момента во внимание не принимается. Если после выполнения оператора switch значение sig равно 0, значит, при помощи маски не удалось найти ни одного ожидающего сигнала.

Если сигнал задерживается, dequeue_signal будет пытаться изъять его из очереди, reset отслеживает, удаляет ли dequeue_signal сигнал из очереди задержанных сигналов для процесса. Начальная установка reset в 1 — это просто предположение, что reset будет изменяться по мере выполнения функции.

Для сигналов не реального времени ядро не сохраняет оригинальную siginfo_t (даже если она существует), поэтому dequeue_signal придется реконструировать как можно больше информации. К сожалению, в данной реализации это не настоль много — только собственно номер сигнала. Остаток полей просто обнуляется.


В случае сигналов реального времени siginfo_t находится где-то рядом. В ее поисках dequeue_signal сканирует sigqueue процесса.

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

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

Из очереди изымался сигнал реального времени, однако он не найден в очереди задержанных сигналов для процесса по причинам, указанным в коде. Сейчас функция dequeue_signal ведет себя так же, как и по отношению к сигналу не реального времени (т.е. знает, что сигнал доступен, но не знает, где он размещается) и предпринимает те же действия по ответу, помещая в info только номер сигнала.

Если не сбросить флаг reset, сигнал обслуживается и удаляется из набора задержанных сигналов для процесса.

Сигнал вытолкнут из очереди, поэтому dequeue_signal должна пересчитать флаг sigpending процесса. Мне здесь видится возможность проведения небольшой оптимизации: dequeue_signal должна делать упомянутое действие только в случае истинного значения reset. recalc_sigpending подсчитывает ответы, полученные ею из наборов заблокированных и ожидающих сигналов для процесса; набор заблокированных сигналов не изменялся, поэтому dequeue_signal должна обращаться к recalc_sigpending лишь при изменении набора ожидающих сигналов. Если значение reset ложно, значит, не изменялся набор ожидающих сигналов, поэтому необходимость в вызове recalc_sigpending отпадает.

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

Возврат количества сигналов, изъятых из очереди, т.е. 0 означает их отсутствие.


Содержание раздела