Читать «Разработка ядра Linux» онлайн - страница 56
Роберт Лав
Как указывалось в предыдущей главе, с приостановленным состоянием связаны два значения поля состояния процесса: TASK_INTERRUPTIBLE
и TASK_UNINTERRUPTIBLE
. Они отличаются только тем, что в состоянии TASK_UNINTERRUPTIBLE
задача игнорирует сигналы, в то время как задачи в состоянии TASK_INTERRUPTIBLE
возвращаются к выполнению преждевременно и обрабатывают пришедший сигнал. Оба типа задач, находящихся в приостановленном состоянии, помещаются в очередь ожидания, ожидают наступления некоторого события и не готовы к выполнению.
Приостановленное состояние обрабатывается с помощью очередей ожидания (wait queue). Очередь ожидания — это просто список процессов, которые ожидают наступления некоторого события. Очереди ожидания в ядре представляются с помощью типа данных wait_queue_head_t
. Они могут быть созданы статически с помощью макроса DECLARE_WAIT_QUEUE_HEAD()
или выделены динамически с последующей инициализацией с помощью функции init_waitqueue_head()
. Процессы помещают себя в очередь ожидания и устанавливают себя в приостановленное состояние. Когда происходит событие, связанное с очередью ожидания, процессы, находящиеся в этой очереди, возвращаются к выполнению. Важно реализовать переход в приостановленное состояние и возврат к выполнению правильно, так чтобы избежать конкуренции за ресурсы (race).
Существуют простые интерфейсы для перехода в приостановленное состояние, и они широко используются. Однако использование этих интерфейсов может привести к состояниям конкуренции: возможен переход в приостановленное состояние
/* пусть q — это очередь ожидания (созданная в другом месте) ,
где мы хотим находиться в приостановленном состоянии */
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(q, &wait);
set_current_state(TASK_INTERRUPTIBLE); /* или TASK_UNINTERRUPTIBLE */
/* переменная condition характеризует наступление события,
которого мы ожидаем */
while (!condition)
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(q, &wait);
Опишем шаги, которые должна проделать задача для того, чтобы поместить себя в очередь ожидания.
• Создать элемент очереди ожидания с помощью макроса DECLARE_WAITQUEUE()
.
• Добавить себя в очередь ожидания с помощью функции add_wait_queue()
. С помощью этой очереди ожидания процесс будет возвращен в состояние готовности к выполнению, когда условие, на выполнение которого ожидает процесс, будет выполнено. Конечно, для этого где-то в другом месте должен быть код, который вызывает функцию wake_up()
для данной очереди, когда произойдет соответствующее событие.