Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
У. Стоулин ГЛАВА 3 Процессы.doc
Скачиваний:
47
Добавлен:
11.05.2015
Размер:
5.19 Mб
Скачать

3.3. Управление процессами

Модели выполнения

Перед тем как обсудить метод, который операционная система использует для управления процессами, нужно разобраться, в чем состоит различие между режимами работы процессора при выполнении кода операционной системы и при выполнении кодов пользовательских программ. Большинство процессоров поддерживают по крайней мере два режима работы. Определенные команды вы­полняются только в более привилегированном режиме. К ним относятся опера­ции считывания или внесения изменений в управляющие регистры (например, операции со словом состояния программы), команды ввода-вывода, а также ко­манды, связанные с управлением памятью. Кроме того, доступ к некоторым областям памяти может быть получен только в более привилегированном режиме.

Режим с меньшими привилегиями часто называют пользовательским (user) режимом, потому что обычно в этом режиме выполняются пользовательские

программы. Режим с более высокими привилегиями называется системным режимом (system mode), режимом управления (control mode) или режимом ядра (kernel mode). В последнем названии упоминается ядро, т.е. та часть операцион­ной системы, которая выполняет важнейшие ее функции. В табл. 3.7 перечислены те из функций операционной системы, которые обычно возлагаются на ядро.

Таблица 3.7. Типичные функции ядра операционной системы

Управление процессами

  • Создание и завершение процессов

  • Планирование и диспетчеризация процессов

  • Переключение процессов

  • Синхронизация и поддержка обмена информацией между процессами

  • Организация управляющих блоков процессов

Управление памятью

  • Выделение адресного пространства процессам

  • Свопинг

  • Управление страницами и сегментами

Управление вводом-выводом

  • Управление буферами

  • Выделение процессам каналов и устройств ввода-вывода

Функции поддержки

  • Обработка прерываний

  • Учет использования ресурсов

  • Текущий контроль системы

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

В связи с этим возникают два вопроса: каким образом процессор может определить, в каком режиме должна выполняться данная программа, и как происходит переключение из одного режима в другой? Что касается ответа на первый вопрос, то в слове состояния программы имеется бит, в котором указывается режим выполне­ния. При некоторых событиях происходит изменение этого бита. Например, если пользователь вызывает службу операционной системы, устанавливается режим ядра (обычно это происходит в результате выполнения команд изменения режима). В качестве примера приведем команду Change Mode (CHM), с помощью которой происхо­дит переключение режима на машинах VAX. Когда пользователь вызывает службу операционной системы или когда в результате прерывания управление переходит к процедуре операционной системы, эта процедура выполняет команду СНМ, чтобы включить более привилегированный режим. Перед тем как вернуть управление пользовательскому процессу, она снова выполняет эту команду, переводя процессор в режим с меньшими привилегиями. Если же команду СНМ попытается выполнить пользовательская программа, это приведет к передаче управления операционной системе, и если такое изменение режима пользовательской программой не разрешено, произойдет ошибка выполнения.

Создание процессов

В разделе 3.1 обсуждались события, влекущие за собой создание новых процессов. Ознакомившись со структурами данных, связанными с процессами, опишем вкратце этапы создания этих процессов.

Если операционная система по какой-либо причине (см. табл. 3.1) приняла решение создать процесс, она может сделать это следующим образом.

  1. Присвоить новому процессу уникальный идентификатор. На этом этапе в первичную таблицу процессов вносится новая запись.

  2. Выделить пространство для процесса. Сюда включаются все элементы образа процесса. Операционная система должна знать, сколько места нужно для пользовательского адресного пространства (для программ и данных) и для пользовательского стека. Эти значения могут назначаться по умолчанию исходя из типа процесса, или могут быть установлены на основе запроса пользователя при создании задания. Если процесс порождается другим процессом, родительский процесс может передать операционной системе необходимые величины, помес­тив их в запрос на создание процесса. Если вновь создающийся процесс будет использовать какую-то часть адресного пространства совместно с другими про­цессами, необходимо установить соответствующие связи. И, наконец, нужно выделить место для управляющего блока процесса.

  3. Инициализировать управляющий блок процесса. Информация о процессе содержит его идентификатор, а также некоторые другие идентификаторы, например идентификатор родительского процесса. Информация о состоянии процессора обычно инициализируется нулевыми значениями, за исключением счетчика команд (который содержит точку входа в программу) и указателей системного стека (задающие границы стека процесса). Инициализация управляющей информации происходит на основе значений, установленных по умолчанию, с учетом атрибутов из запроса на создание процесса. Например, состояние процесса обычно инициализируется значением "готов" или "готов и приос­тановлен". Что касается приоритета, то по умолчанию он может быть установлен минимальным, если не поступил явный запрос на установку более высокого приоритета. Поначалу процесс может не владеть никакими ресурсами (типа устройств ввода-вывода или файлов), если не сделан явный запрос или если эти ресурсы не были переданы по наследству от родительского процесса.

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

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

Переключение процессов

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

Когда нужно переключать процессы

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

Таблица 3.8. Механизмы прерывания процесса

Механизм Причина Использует

Прерывание Внешняя по отношению к - Отклик на внешнее асинхронное

выполнению текущей команды событие

Ловушка Связана с выполнением текущей Обработку ошибки или исключительной

команды ситуации

Вызов

супервизора Запрос приложения Вызов функции операционной

системы

Во-первых, рассмотрим системные прерывания. Фактически имеются сис­темные прерывания двух видов. Первый вид — обычные прерывания, а второй — ловушки (trap). Прерывания первого вида происходят из-за событий оп­ределенного типа, не связанных с выполняющимся процессом и являющихся внешними по отношению к нему (таким событием может быть, например, за­вершение операции ввода-вывода). Ловушки связаны с ошибкой или исключи­тельной ситуацией, возникшей в результате выполнения текущего процесса. В качестве примера можно привести попытку получения незаконного доступа к файлу. При обычном прерывании управление передается обработчику прерыва­ний, который осуществляет некоторые подготовительные действия, а затем — функции операционной системы, отвечающей за прерывания данного вида. При­ведем конкретные примеры прерываний.

  • Прерывание таймера. Операционная система определяет, что текущий процесс выполняется в течение максимально разрешенного промежутка времени. Если это так, то данный процесс нужно переключить в состояние готовности и передать управление другому процессу.

  • Прерывание ввода-вывода. Операционная система определяет, что именно произошло, и если это то событие, которого ожидают один или несколько процессов, операционная система переводит все соответствующие блокированные процессы в состояние готовности (соответственно, блокированные

приостановленные процессы она переводит в состояние готовых приостановленных процессов). Затем операционная система должна принять решение: возобновить выполнение текущего процесса или передать управление готовому к выполнению процессу с более высоким приоритетом.

• Ошибка отсутствия блока в памяти. Допустим, что процессор должен обратиться к слову виртуальной памяти, которое в настоящий момент отсутствует в основной памяти. При этом операционная система должна загрузить в основную память блок (страницу или сегмент), в котором содержится ад­ресованное слово. Сразу же после запроса на загрузку блока операционная система может передать управление другому процессу, а процесс, для про­должения выполнения которого нужно загрузить блок в основную память, переходит в блокированное состояние. После загрузки нужного блока этот процесс переходит в состояние готовности.

В случае возникновения ловушки (trap) операционная система определяет, яв­ляется ли ошибка или исключительная ситуация фатальной. Если это так, то вы­полняющийся в данный момент процесс переходит в состояние завершающегося, а управление переходит к другому процессу. В противном случае действия операцион­ной системы будут зависеть от характера происшедшей ошибки, а также от конст­рукции самой операционной системы. Может быть предпринята попытка выполнить восстановительные процедуры или просто поставить пользователя в известность о происшедшей ошибке. Операционная система при этом может как выполнить пере­ключение процессов, так и продолжить выполнение текущего процесса.

Наконец, операционная система может быть активизирована в результате вы­зова супервизора (supervisor call), который исходит от выполняемой программы. Например, пусть в ходе работы пользовательского процесса нужно выполнить ко­манду, для которой требуется операция ввода-вывода, например открытие файла. Такой вызов приведет к тому, что управление перейдет к процедуре, являющейся частью кода операционной системы. Вообще говоря, использование таких системных вызовов приводит к переходу процесса в блокированное состояние.

Переключение режимов

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

  1. Сохраняет контекст текущей программы.

  2. Устанавливает в счетчике команд начальный адрес программы — обработчика прерываний.

  3. Переключается из пользовательского режима в режим ядра, чтобы можно было выполнять привилегированные команды, содержащиеся в коде обработки прерывания.

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

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

Нужно ли сделать что-нибудь еще? Это зависит от дальнейших событий. Обычно обработчик прерываний является короткой программой, которая выполняет несколько базовых действий, связанных с прерыванием. Например, эта программа восстанавливает состояние флага, сигнализирующего о наличии прерываний. Она может послать подтверждение о получении прерывания тому элементу аппаратного обеспечения, который сгенерировал это прерывание (например, контроллеру ввода-вывода). Кроме того, эта программа может выполнить некоторые служебные действия, связанные с событием, сгенерировавшим прерывание. Например, если прерывание связано с вводом-выводом, обработчик прерываний проверит, не произошло ли ошибки при его выполнении. Если произошла ошибка, обработчик может послать сигнал процессу, первоначально выдавшему запрос на операцию ввода-вывода. Если прерывание сгенерировано таймером, программа обработки прерываний передаст управление диспетчеру. Диспетчер выполнит переключение процессора на обработку другого процесса, если промежуток времени, отведенный на выполнение текущего процесса, уже истек.

Как же быть с остальной информацией, содержащейся в управляющем блоке процесса? Если вслед за данным прерыванием последует переключение на другой процесс, то нужно выполнить соответствующие действия по переключе­нию. Однако в большинстве операционных систем прерывание не обязательно влечет за собой переключение процессов. По окончании работы обработчика пре­рываний возможно возобновление выполнения того процесса, который выпол­нялся и до прерывания. В некоторых случаях во время прерывания достаточно сохранить только информацию о состоянии процессора. После того как управление вновь возвратится к выполнявшейся перед прерыванием программе, нужно будет лишь восстановить эту информацию. Обычно функция сохранения и восстановления состояния процессора возлагается на аппаратное обеспечение.

Изменение состояния процесса

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

10 В литературе по операционным системам часто встречается термин переклю­чение контекста (context switch). К сожалению, хотя в большинстве изданий этот термин используется для обозначения действия, которое в нашей книге называется переключением процессов, в других источниках он используется для обозначения переключения режима работы процессора или даже переключения потоков (о котором пойдет речь в следующей главе). Поэтому термин переключение контекста в данной книге во избежание его неоднозначного понимания не используется.

Ядро вне процессов

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

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

Выполнение в составе пользовательских процессов

На небольших машинах (персональных компьютерах, рабочих станциях) часто применяется альтернативный подход, при котором почти все программы операционной системы выполняются в контексте пользовательского процесса. Разработчики таких систем придерживаются той точки зрения, что операцион­ная система — это в основном набор процедур, которые вызываются для выпол­нения различных функций пользовательского процесса. Этот подход проиллюстрирован на рис. 3.12,6. Каждый процесс, принятый операционной системой на обработку, включает в себя не только блоки, изображенные на рис. 3.10, но и области кода, данных и стека программ ядра.

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

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

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

В некотором отношении такая точка зрения на операционную систему является довольно интересной. Выполняющийся процесс в определенный момент времени сам сохраняет информацию о своем состоянии, выбирает для выполнения другой процесс, находящийся в состоянии готовности, и передает ему управление. Причина того, что в такой ситуации не наступает хаос и произвол, заключается в том, что критичный код представляет собой не код пользователь­ской программы, а совместно используемый код операционной системы, выпол­няющийся в контексте процесса. В силу наличия пользовательского режима и режима ядра пользователь не может вмешиваться в работу системных процедур, хотя они и выполняются в среде пользовательского процесса. Это еще раз напоминает нам об отличиях концепций процесса и программы и о том, что между ними нельзя ставить знак равенства. В ходе процесса могут выполняться и пользовательские программы, и программы операционной системы; с другой стороны, программы операционной системы, выполняемые в разных пользовательских процессах, являются идентичными.

Операционная система на основе процессов

Еще одним вариантом построения операционной системы, проиллюстрированным на рис. 3.12,в, является ее реализация в виде набора системных процессов. Так же, как и при других подходах, программы, входящие в ядро, выполняются в ре­жиме ядра, однако в этом случае основные функции ядра организованы как отдель­ные процессы. Здесь также возможно наличие небольшого кода, который является внешним по отношению ко всем процессам и осуществляет их переключение.

Такой подход обладает рядом преимуществ. Его применение дисциплинирует программистов и способствует разработке модульных операционных систем с минимальными простыми межмодульными интерфейсами. Кроме того, некоторые второстепенные функции операционных систем удобно реализовывать в виде отдельных процессов. Например, ранее упоминалась управляющая программа, которая ведет запись интенсивности использования различных ресурсов (процессора, памяти, каналов) и скорости выполнения процессов в системе. По­скольку эта программа не обслуживает какой-то конкретный активный процесс, она может вызываться только операционной системой. Как процесс эта про­грамма может выполняться с определенным приоритетом и чередоваться с дру­гими программами под управлением диспетчера. И наконец, реализация опера­ционной системы в виде набора процессов полезна в многопроцессорных и многокомпьютерных системах, в которых отдельные службы операционной системы могут быть переданы для выполнения специально предназначенным процессо­рам, что позволит повысить производительность системы.