Разработка ядра Linux | страница 64



. Они могут быть созданы статически с помощью макроса >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() для данной очереди, когда произойдет соответствующее событие.

• Изменить состояние процесса в значение >TASK_INTERRUPTIBLE или >TASK_UNINTERRUPTIBLE.

• Проверить, не выполнилось ли ожидаемое условие. Если выполнилось, то больше нет необходимости переходить в приостановленное состояние. Если нет, то вызвать функцию >schedule().

• Когда задача становится готовой к выполнению, она снова проверяет выполнение ожидаемого условия. Если условие выполнено, то производится выход из цикла. Если нет, то снова вызывается функция