Читать «Разработка ядра Linux» онлайн - страница 29

Роберт Лав

Рис. 3.3. Диаграмма состояний процесса

Эти состояния представляются значением одного из пяти возможных флагов, описанных ниже.

• TASK_RUNNING — процесс готов к выполнению (runnable). Иными словами, либо процесс выполняется в данный момент, либо находится в одной из очередей процессов, ожидающих на выполнение (эти очереди, runqueue, обсуждаются в главе 4. "Планирование выполнения процессов").

• TASK_INTERRUPTIBLE — процесс приостановлен (находится в состоянии ожидания, sleeping), т.е. заблокирован в ожидании выполнения некоторого условия. Когда это условие выполнится, ядро переведет процесс в состояние TASK_RUNNING. Процесс также возобновляет выполнение (wake up) преждевременно при получении им сигнала.

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

• TASK_ZOMBIE — процесс завершен, однако порождающий его процесс еще не вызвал системный вызов wait4(). Дескриптор такого процесса должен оставаться доступным на случай, если родительскому процессу потребуется доступ к этому дескриптору. Когда родительский процесс вызывает функцию wait4(), то такой дескриптор освобождается.

• TASK_STOPPED — выполнение процесса остановлено. Задача не выполняется и не имеет право выполняться. Такое может случиться, если задача получает какой-либо из сигналов SIGSTOP, SIGTSTP, SIGTTIN или SIGTTOU, а также если сигнал приходит в тот момент, когда процесс находится в состоянии отладки.

Манипулирование текущим состоянием процесса

Исполняемому коду ядра часто необходимо изменять состояние процесса. Наиболее предпочтительно для этого использовать функцию

set_task state(task, state);

/* установить задание 'task' в состояние 'state' */

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

task->state = state;

Вызов set_current_state(state) является синонимом к вызову set_task_state(current, state).

Контекст процесса

Одна из наиболее важных частей процесса— это исполняемый программный код. Этот код считывается из выполняемого файла (executable) и выполняется в адресном пространстве процесса. Обычно выполнение программы осуществляется в пространстве пользователя. Когда программа выполняет системный вызов (см. главу 5, "Системные вызовы") или возникает исключительная ситуация, то программа входит в пространство ядра.

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