Переход в приостановленное состояние и возврат к выполнению

Переход в приостановленное состояние и возврат к выполнению

Приостановленное состояние задачи (состояние ожидания, заблокированное состояние, sleeping, blocked) представляет собой специальное состояние задачи, в котором задание не выполняется. Это является очень важным, так как в противном случае планировщик выбирал бы на выполнение задания, которые не "хотят" выполняться, или, хуже того, состояние ожидания должно было бы быть реализовано в виде цикла, занимающего время процессора. Задачи могут переходить в приостановленное состояние по нескольким причинам, но в любом случае— в ожидании наступления некоторого события. Событием может быть ожидание наступления некоторого момента времени, ожидание следующей порции данных при файловом вводе-выводе или другое событие в аппаратном обеспечении. Задача также может переходить в приостановленное состояние непроизвольным образом, когда она пытается захватить семафор в режиме ядра (эта ситуация рассмотрена в главе 9, "Средства синхронизации в ядре"). Обычная причина перехода в приостановленное состояние — это выполнение операций файлового ввода-вывода, например задание вызывает функцию read() для файла, который необходимо считать с диска. Еще один пример— задача может ожидать на ввод данных с клавиатуры. В любом случае ядро ведет себя одинаково: задача помечает себя как находящуюся в приостановленном состоянии, помещает себя в очередь ожидания (wail queue), удаляет себя из очереди выполнения и вызывает функцию schedule() для выбора нового процесса на выполнение. Возврат к выполнению (wake up) происходит в обратном порядке: задача помечает себя как готовую к выполнению, удаляет себя из очереди ожидания и помещает себя в очередь выполнения.

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

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

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

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

• Когда условие выполнено, задача может установить свое состояние в значение TASK_RUNNING и удалить себя из очереди ожидания с помощью функции remove_wait_queue().

Если условие выполнится перед тем, как задача переходит в приостановленное состояние, то цикл прервется и задача не перейдет в приостановленное состояние по ошибке. Следует заметить, что во время выполнения тела цикла код ядра часто может выполнять и другие задачи. Например, перед выполнением функции schedule() может возникнуть необходимость освободить некоторые блокировки и захватить их снова после возврата из этой функции; если процессу был доставлен сигнал, то необходимо возвратить значение -ERESTARTSYS; может возникнуть необходимость отреагировать на некоторые другие события.

Возврат к выполнению (wake up) производится с помощью функции wake_up(), которая возвращает все задачи, ожидающие в данной очереди, в состояние готовности к выполнению. Вначале вызывается функция try_to_wake_up(), которая устанавливает поле состояния задачи в значение TASK_RUNNING, далее вызывается функция activate_task() для добавления задачи в очередь выполнения и устанавливается флаг need_resched в ненулевое значение, если приоритет задачи, которая возвращается к выполнению, больше приоритета текущей задачи. Код, который отвечает за наступление некоторого события, обычно вызывает функцию wake_up() после того, как это событие произошло. Например, после того как данные прочитаны с жесткого диска, подсистема VFS вызывает функцию wake_up() для очереди ожидания, которая содержит все процессы, ожидающие поступления данных.

Важным может быть замечание о том, что переход в приостановленное состояние часто сопровождается ложными переходами к выполнению. Это возникает потому, что переход задачи в состояние выполнения не означает, что событие, которого ожидала задача, уже наступило: поэтому переход в приостановленное состояние должен всегда выполняться в цикле, который гарантирует, что условие, на которое ожидает задача, действительно выполнилось (рис. 4.3).

Рис. 4.3. Переход в приостановленное состояние (sleeping) и возврат к выполнению (wake up)

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

4.6.4 Возврат Значения

Из книги C++ автора Хилл Мюррей

4.6.4 Возврат Значения Из функции, которая не описана как void, можно (и долно) возвращать значение. Возвращаемое значение задается опратором return. Например:int fac(int n) (*return (n»1) ? n*fac(n-1) : 1; *)В функции может быть больше одного оператора return: int fac(int n) (* if (n » 1) return n*fac(n-1); else return 1; *)Как и


Обязательства по выполнению

Из книги Модель зрелости процессов разработки программного обеспечения автора Паулк Марк

Обязательства по выполнению Описывают действия, которые должна выполнить организация, чтобы обеспечить установление и стабильность процесса. Обязательства по выполнению обычно касаются установления организационных политик и поддержки со стороны высшего


Обязательства по выполнению

Из книги Интернет-шопинг для неопытных пользователей автора Шестопалова Елена

Обязательства по выполнению Обязательство 1 Проект следует документу организационной политики управления системными требованиями, отнесенными к ПО.В рамках этих практик системные требования, отнесенные к ПО, называются «установленными требованиями».Установленные


Обязательства по выполнению

Из книги C++ для начинающих автора Липпман Стенли

Обязательства по выполнению Обязательство 1 Должен быть назначен производственный менеджер проекта, в обязанности которого входит обсуждение обязательств и подготовка плана разработки ПО.Обязательство 2 Проект следует документированной организационной политике по


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1 Должен быть назначен производственный менеджер проекта, ответственный за работы по проекту и их результаты. Обязательство 2 Проект следует документированной организационной политике управления проектом разработки ПО.Эта


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1 Проект следует документированной организационной политике управления производственным субподрядом.Эта политика обычно состоит из следующих положений:1. При выборе субподрядчиков и управлении договорами по субподряду


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1 Проект следует документированной организационной политике по обеспечению качества ПО.Эта политика обычно состоит из следующих положений.1. Группа обеспечения качества контролирует работу по всем проектам разработки в


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1 Проект следует документированной организационной политике управления конфигурацией ПО (Software Configuration Management, SCM).Эта политика обычно состоит из следующих положений:1. По каждому проекту должны быть назначены конкретные лица,


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1. Организация следует документированной политике разработки и сопровождения СППО и связанных с ним основных средств.Основные средства ППО:стандартный производственный процесс организации,инструкции и критерии для адаптации


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1. Организация следует документированной политике предоставления необходимого обучения.Эта политика обычно состоит из следующих положений:1. Должны быть определены навыки и знания, необходимые для каждой руководящей или


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1. Проект следует документированной организационной политике, согласно которой планирование проекта и управление им должно проводиться с использованием СППО и связанных с ним основных средств.Практики, касающиеся СППО и


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1. Проект следует документированной организационной политике выполнения операций по разработке ПО.Эта политика обычно состоит из следующих положений:1. Операции разработки ПО выполняются в соответствии с производственным


Обязательства по выполнению

Из книги автора

Обязательства по выполнению Обязательство 1. Проект следует документированной организационной политике проведения экспертных оценок.Эта политика обычно состоит из следующих положений:1. Организация определяет стандартный набор промежуточных программных продуктов,


Возврат товара

Из книги автора

Возврат товара Очень интересный момент, который обязательно надо обговорить. Во всех интернет-магазинах свои правила возврата товара, но российское законодательство все равно прописывает общие правила для всех. Если вы получили товар ненадлежащего качества, то мнения


Возврат товара

Из книги автора

Возврат товара Перед тем, как завершить оформление заказа, было бы неплохо прочитать условия возврата. Некоторые магазины пишут, что возврат из-за рубежа невозможен, другие относятся к этому нормально, и вместе с заказом присылают лист возврата, если вы вдруг что-то


7.4. Возврат значения

Из книги автора

7.4. Возврат значения В теле функции может встретиться инструкция return. Она завершает выполнение функции. После этого управление возвращается той функции, из которой была вызвана данная. Инструкция return может употребляться в двух формах:return;return expression;Первая форма