6.1 СОСТОЯНИЯ ПРОЦЕССА И ПЕРЕХОДЫ МЕЖДУ НИМИ 
 
Как уже отмечалось в главе
2, время жизни процесса можно
теоретически разбить на несколько
состояний, описывающих процесс.
Полный набор состояний процесса
содержится в следующем перечне:  
    - Процесс выполняется в режиме
        задачи. 
 
    - Процесс выполняется в режиме
        ядра. 
 
    - Процесс не выполняется, но
        готов к запуску под
        управлением ядра. 
 
    - Процесс приостановлен и
        находится в оперативной
        памяти. 
 
    - Процесс готов к запуску, но
        программа подкачки (нулевой
        процесс) должна еще загрузить
        процесс в оперативную память,
        прежде чем он будет запущен под
        управлением ядра. Это
        состояние будет предметом
        обсуждения в главе
        9 при рассмотрении системы
        подкачки. 
 
    - Процесс приостановлен и
        программа подкачки выгрузила
        его во внешнюю память, чтобы в
        оперативной памяти освободить
        место для других процессов. 
 
    - Процесс возвращен из
        привилегированного режима
        (режима ядра) в
        непривилегированный (режим
        задачи), ядро резервирует его и
        переключает контекст на другой
        процесс. Об отличии этого
        состояния от состояния 3
        (готовность к запуску) пойдет
        речь ниже. 
 
    - Процесс вновь создан и
        находится в переходном
        состоянии; процесс существует,
        но не готов к выполнению, хотя и
        не приостановлен. Это
        состояние является начальным
        состоянием всех процессов,
        кроме нулевого. 
 
    - Процесс вызывает системную
        функцию exit и прекращает
        существование. Однако, после
        него осталась запись,
        содержащая код выхода, и
        некоторая хронометрическая
        статистика, собираемая
        родительским процессом. Это
        состояние является последним
        состоянием процесса. 
 
 
Рисунок 6.1 представляет
собой полную диаграмму переходов
процесса из состояния в состояние.
Рассмотрим с помощью модели
переходов типичное поведение
процесса. Ситуации, которые будут
обсуждаться, несколько
искусственны и процессы не всегда
имеют дело с ними, но эти ситуации
вполне применимы для иллюстрации
различных переходов. Начальным
состоянием модели является
создание процесса родительским
процессом с помощью системной
функции fork; из этого состояния
процесс неминуемо переходит в
состояние готовности к запуску (3
или 5). Для простоты предположим, что
процесс перешел в состояние
"готовности к запуску в
памяти" (3). Планировщик процессов
в конечном счете выберет процесс
для выполнения и процесс перейдет в
состояние "выполнения в режиме
ядра", где доиграет до конца роль,
отведенную ему функцией fork. 
 
   
Рисунок 6.1. Диаграмма переходов
процесса из состояния в состояние
 
После всего этого процесс может
перейти в состояние "выполнения
в режиме задачи". По прохождении
определенного периода времени
может произойти прерывание работы
процессора по таймеру и процесс
снова перейдет в состояние
"выполнения в режиме ядра". Как
только программа обработки
прерывания закончит работу, ядру
может понадобиться подготовить к
запуску другой процесс, поэтому
первый процесс перейдет в
состояние "резервирования",
уступив дорогу второму процессу.
Состояние "резервирования" в
действительности не отличается от
состояния "готовности к запуску
в памяти" (пунктирная линия на
рисунке, соединяющая между собой
оба состояния, подчеркивает их
эквивалентность), но они выделяются
в отдельные состояния, чтобы
подчеркнуть, что процесс,
выполняющийся в режиме ядра, может
быть зарезервирован только в том
случае, если он собирается
вернуться в режим задачи.
Следовательно, ядро может при
необходимости подкачивать процесс
из состояния "резервирования".
При известных условиях планировщик
выберет процесс для исполнения и
тот снова вернется в состояние
"выполнения в режиме задачи".  
Когда процесс выполняет вызов
системной функции, он из состояния
"выполнения в режиме задачи"
переходит в состояние
"выполнения в режиме ядра".
Предположим, что системной функции
требуется ввод-вывод с диска и
поэтому процесс вынужден
дожидаться завершения
ввода-вывода. Он переходит в
состояние "приостанова в
памяти", в котором будет
находиться до тех пор, пока не
получит извещения об окончании
ввода-вывода. Когда ввод-вывод
завершится, произойдет аппаратное
прерывание работы центрального
процессора и программа обработки
прерывания возобновит выполнение
процесса, в результате чего он
перейдет в состояние "готовности
к запуску в памяти".  
Предположим, что система
выполняет множество процессов,
которые одновременно никак не
могут поместиться в оперативной
памяти, и программа подкачки
(нулевой процесс) выгружает один
процесс, чтобы освободить место для
другого процесса, находящегося в
состоянии "готов к запуску, но
выгружен". Первый процесс,
выгруженный из оперативной памяти,
переходит в то же состояние. Когда
программа подкачки выбирает
наиболее подходящий процесс для
загрузки в оперативную память, этот
процесс переходит в состояние
"готовности к запуску в
памяти". Планировщик выбирает
процесс для исполнения и он
переходит в состояние
"выполнения в режиме ядра".
Когда процесс завершается, он
исполняет системную функцию exit,
последовательно переходя в
состояния "выполнения в режиме
ядра" и, наконец, в состояние
"прекращения существования".  
Процесс может управлять
некоторыми из переходов на уровне
задачи. Во-первых, один процесс
может создать другой процесс. Тем
не менее, в какое из состояний
процесс перейдет после создания
(т.е. в состояние "готов к
выполнению, находясь в памяти"
или в состояние "готов к
выполнению, но выгружен") зависит
уже от ядра. Процессу эти состояния
не подконтрольны. Во-вторых,
процесс может обратиться к
различным системным функциям,
чтобы перейти из состояния
"выполнения в режиме задачи" в
состояние "выполнения в режиме
ядра", а также перейти в режим
ядра по своей собственной воле. Тем
не менее, момент возвращения из
режима ядра от процесса уже не
зависит; в результате каких-то
событий он может никогда не
вернуться из этого режима и из него
перейдет в состояние
"прекращения существования" (см. раздел 7.2, где
говорится о сигналах). Наконец,
процесс может завершиться с
помощью функции exit по своей
собственной воле, но как
указывалось ранее, внешние события
могут потребовать завершения
процесса без явного обращения к
функции exit. Все остальные переходы
относятся к жестко закрепленной
части модели, закодированной в
ядре, и являются результатом
определенных событий, реагируя на
них в соответствии с правилами,
сформулированными в этой и
последующих главах. Некоторые из
правил уже упоминались: например,
то, что процесс может выгрузить
другой процесс, выполняющийся в
ядре.  
Две принадлежащие ядру структуры
данных описывают процесс: запись в
таблице процессов и пространство
процесса. Таблица процессов
содержит поля, которые должны быть
всегда доступны ядру, а
пространство процесса - поля,
необходимость в которых возникает
только у выполняющегося процесса.
Поэтому ядро выделяет место для
пространства процесса только при
создании процесса: в нем нет
необходимости, если записи в
таблице процессов не соответствует
конкретный процесс.  
Запись в таблице процессов
состоит из следующих полей:  
    - Поле состояния, которое
        идентифицирует состояние
        процесса. 
 
    - Поля, используемые ядром при
        размещении процесса и его
        пространства в основной или
        внешней памяти. Ядро
        использует информацию этих
        полей для переключения
        контекста на процесс, когда
        процесс переходит из состояния
        "готов к выполнению,
        находясь в памяти" в
        состояние "выполнения в
        режиме ядра" или из
        состояния
        "резервирования" в
        состояние "выполнения в
        режиме задачи". Кроме того,
        ядро использует эту информацию
        при перекачки процессов из и в
        оперативную память (между
        двумя состояниями "в
        памяти" и двумя состояниями
        "выгружен"). Запись в
        таблице процессов содержит
        также поле, описывающее размер
        процесса и позволяющее ядру
        планировать выделение
        пространства для процесса. 
 
    - Несколько пользовательских
        идентификаторов (UID),
        устанавливающих различные
        привилегии процесса. Поля UID,
        например, описывают
        совокупность процессов,
        могущих обмениваться
        сигналами (см. следующую главу).
    
 
    - Идентификаторы процесса (PID),
        указывающие взаимосвязь между
        процессами. Значения полей PID
        задаются при переходе процесса
        в состояние "создан" во
        время выполнения функции fork. 
 
    - Дескриптор события
        (устанавливается тогда, когда
        процесс приостановлен). В
        данной главе будет рассмотрено
        использование дескриптора
        события в алгоритмах функций
        sleep и wakeup. 
 
    - Параметры планирования,
        позволяющие ядру
        устанавливать порядок
        перехода процессов из
        состояния "выполнения в
        режиме ядра" в состояние
        "выполнения в режиме
        задачи". 
 
    - Поле сигналов, в котором
        перечисляются сигналы,
        посланные процессу, но еще не
        обработанные (раздел
        7.2). 
 
    - Различные таймеры, описывающие
        время выполнения процесса и
        использование ресурсов ядра и
        позволяющие осуществлять
        слежение за выполнением и
        вычислять приоритет
        планирования процесса. Одно из
        полей является таймером,
        который устанавливает
        пользователь и который
        необходим для посылки процессу
        сигнала тревоги (раздел
        8.3). Пространство процесса
        содержит поля, дополнительно
        характеризующие состояния
        процесса. В предыдущих главах
        были рассмотрены последние
        семь из приводимых ниже полей
        пространства процесса, которые
        мы для полноты вновь кратко
        перечислим: 
 
    - Указатель на таблицу
        процессов, который
        идентифицирует запись,
        соответствующую процессу. 
 
    - Пользовательские
        идентификаторы,
        устанавливающие различные
        привилегии процесса, в
        частности, права доступа к
        файлу (см. раздел 7.6).
    
 
    - Поля таймеров, хранящие время
        выполнения процесса (и его
        потомков) в режиме задачи и в
        режиме ядра. 
 
    - Вектор, описывающий реакцию
        процесса на сигналы. 
 
    - Поле операторского терминала,
        идентифицирующее
        "регистрационный
        терминал", который связан с
        процессом. 
 
    - Поле ошибок, в которое
        записываются ошибки, имевшие
        место при выполнении системной
        функции. 
 
    - Поле возвращенного значения,
        хранящее результат выполнения
        системной функции. 
 
    - Параметры ввода-вывода: объем
        передаваемых данных, адрес
        источника (или приемника)
        данных в пространстве задачи,
        смещения в файле (которыми
        пользуются операции
        ввода-вывода) и т.д. 
 
    - Имена текущего каталога и
        текущего корня, описывающие
        файловую систему, в которой
        выполняется процесс. 
 
    - Таблица пользовательских
        дескрипторов файла, которая
        описывает файлы, открытые
        процессом. 
 
    - Поля границ, накладывающие
        ограничения на размерные
        характеристики процесса и на
        размер файла, в который процесс
        может вести запись. 
 
    - Поле прав доступа, хранящее
        двоичную маску установок прав
        доступа к файлам, которые
        создаются процессом.
        Пространство состояний
        процесса и переходов между
        ними рассматривалось в данном
        разделе на логическом уровне.
        Каждое состояние имеет также
        физические характеристики,
        управляемые ядром, в частности,
        виртуальное адресное
        пространство процесса.
        Следующий раздел посвящен
        описанию модели распределения
        памяти; в остальных разделах
        состояния процесса и переходы
        между ними рассматриваются на
        физическом уровне, особое
        внимание при этом уделяется
        состояниям "выполнения в
        режиме задачи",
        "выполнения в режиме
        ядра", "резервирования"
        и "приостанова (в памяти)".
        В следующей главе
        затрагиваются состояния
        "создания" и
        "прекращения
        существования", а в главе 8 - состояние
        "готовности к запуску в
        памяти". В главе
        9 обсуждаются два состояния
        выгруженного процесса и
        организация подкачки по
        обращению. 
 
 
Предыдущая
глава || Оглавление
|| Следующая глава 
  
 
 |