ГЛАВА 6. СТРУКТУРА ПРОЦЕССОВ В главе 2 были сформулированы характеристики процессов. В настоящей гла- ве на более формальном уровне определяется понятие "контекст процесса" и по- казывается, каким образом ядро идентифицирует процесс и определяет его мес- тонахождение. В разделе 6.1 описаны модель состояний процессов для системы UNIX и последовательность возможных переходов из состояния в состояние. В ядре находится таблица процессов, каждая запись которой описывает состояние одного из активных процессов в системе. В пространстве процесса хранится до- полнительная информация, используемая в управлении протеканием процесса. За- пись в таблице процессов и пространство процесса составляют в совокупности контекст процесса. Аспектом контекста процесса, наиболее явно отличающим данный контекст от контекста другого процесса, без сомнения является содер- жимое адресного пространства процесса. В разделе 6.2 описываются принципы управления распределением памяти для процессов и ядра, а также взаимодейст- вие операционной системы с аппаратными средствами при трансляции виртуальных адресов в физические. Раздел 6.3 посвящен рассмотрению составных элементов контекста процесса, а также описанию алгоритмов управления контекстом про- цесса. Раздел 6.4 демонстрирует, каким образом осуществляется сохранение контекста процесса ядром в случае прерывания, вызова системной функции или переключения контекста, а также каким образом возобновляется выполнение при- остановленного процесса. В разделе 6.5 приводятся различные алгоритмы, ис- пользуемые в тех системных функциях, которые работают с адресным пространст- вом процесса и которые будут рассмотрены в следующей главе. И, наконец, в разделе 6.6 рассматриваются алгоритмы приостанова и возобновления выполнения процессов. 6.1 СОСТОЯНИЯ ПРОЦЕССА И ПЕРЕХОДЫ МЕЖДУ НИМИ Как уже отмечалось в главе 2, время жизни процесса можно теоретически разбить на несколько состояний, описывающих процесс. Полный набор состояний процесса содержится в следующем перечне: 1. Процесс выполняется в режиме задачи. 2. Процесс выполняется в режиме ядра. 3. Процесс не выполняется, но готов к запуску под управлением ядра. 4. Процесс приостановлен и находится в оперативной памяти. 5. Процесс готов к запуску, но программа подкачки (нулевой процесс) должна еще загрузить процесс в оперативную память, прежде чем он будет запущен под управлением ядра. Это состояние будет предметом обсуждения в главе 9 при рассмотрении системы подкачки. 6. Процесс приостановлен и программа подкачки выгрузила его во внешнюю па- мять, чтобы в оперативной памяти освободить место для других процессов. 7. Процесс возвращен из привилегированного режима (режима ядра) в неприви- легированный (режим задачи), ядро резервирует его и переключает контекст на другой процесс. Об отличии этого состояния от состояния 3 (готовность к запуску) пойдет речь ниже. 8. Процесс вновь создан и находится в переходном состоянии; процесс сущест- вует, но не готов к выполнению, хотя и не приостановлен. Это состояние является начальным состоянием всех процессов, кроме нулевого. 9. Процесс вызывает системную функцию exit и прекращает существование. Од- нако, после него осталась запись, содержащая код выхода, и некоторая хронометрическая статистика, собираемая родительским процессом. Это сос- 137 тояние является последним состоянием процесса. Рисунок 6.1 представляет собой полную диаграмму переходов процесса из состояния в состояние. Рассмотрим с помощью модели переходов ти- пичное поведение процесса. Ситуации, которые будут обсуждаться, несколько искусственны и процессы не всегда имеют дело с ними, но эти ситуации вполне Выполняется в режиме задачи +-------+ | 1 | Вызов функ- | | ции, преры- ++------+ вание | ^ ^ Преры- +-----+ +-------+ | | вание, | | | +-------+ +---+ Возврат в возврат| | | | Возврат | режим задачи из пре-| | | | | рыва-| v v | Выполняет- | +-------+ ния | +------++ся в режи- ++------+ | | +-->| |ме ядра | | | 9 |<-----------+ 2 +------------>| 7 | | | Выход | | Резервирует-| | +-------+ ++------+ ся +-------+ Прекращение | ^ - Зарезер- существования | | - вирован +---------------+ +------+ -------- | Приостанов Запуск | - v | - При-+-------+ +-+-----+ Готов к ос- | | Возобновление | | запуску та- | 4 +----------------------->| 3 | в памяти нов-| | | | лен +---+---+ ++------+ в па- | | ^ ^ мяти | | | | Достаточно | | | | памяти | | | +---+ | Вы- Вы- | | | | грузка грузка | | | Создан | | |За- ++------+ | | |груз-| | fork | | |ка | 8 |<----- | | | ++------+ | | | | Недоста- | | | +---+ точно | | | | памяти | | | | (только система | | | | подкачки) v v | v +-------+ +---+---+ | | Возобновление | | | 6 +----------------------->| 5 | +-------+ +-------+ Приостановлен, Готов к запуску, выгружен выгружен Рисунок 6.1. Диаграмма переходов процесса из состояния в сос- тояние 138 применимы для иллюстрации различных переходов. Начальным состоянием модели является создание процесса родительским процессом с помощью системной функ- ции fork; из этого состояния процесс неминуемо переходит в состояние готов- ности к запуску (3 или 5). Для простоты предположим, что процесс перешел в состояние "готовности к запуску в памяти" (3). Планировщик процессов в ко- нечном счете выберет процесс для выполнения и процесс перейдет в состояние "выполнения в режиме ядра", где доиграет до конца роль, отведенную ему функ- цией fork. После всего этого процесс может перейти в состояние "выполнения в режиме задачи". По прохождении определенного периода времени может произойти преры- вание работы процессора по таймеру и процесс снова перейдет в состояние "вы- полнения в режиме ядра". Как только программа обработки прерывания закончит работу, ядру может понадобиться подготовить к запуску другой процесс, поэто- му первый процесс перейдет в состояние "резервирования", уступив дорогу вто- рому процессу. Состояние "резервирования" в действительности не отличается от состояния "готовности к запуску в памяти" (пунктирная линия на рисунке, соединяющая между собой оба состояния, подчеркивает их эквивалентность), но они выделяются в отдельные состояния, чтобы подчеркнуть, что процесс, выпол- няющийся в режиме ядра, может быть зарезервирован только в том случае, если он собирается вернуться в режим задачи. Следовательно, ядро может при необ- ходимости подкачивать процесс из состояния "резервирования". При известных условиях планировщик выберет процесс для исполнения и тот снова вернется в состояние "выполнения в режиме задачи". Когда процесс выполняет вызов системной функции, он из состояния "выпол- нения в режиме задачи" переходит в состояние "выполнения в режиме ядра". Предположим, что системной функции требуется ввод-вывод с диска и поэтому процесс вынужден дожидаться завершения ввода-вывода. Он переходит в состоя- ние "приостанова в памяти", в котором будет находиться до тех пор, пока не получит извещения об окончании ввода-вывода. Когда ввод-вывод завершится, произойдет аппаратное прерывание работы центрального процессора и программа обработки прерывания возобновит выполнение процесса, в результате чего он перейдет в состояние "готовности к запуску в памяти". Предположим, что система выполняет множество процессов, которые одновре- менно никак не могут поместиться в оперативной памяти, и программа подкачки (нулевой процесс) выгружает один процесс, чтобы освободить место для другого процесса, находящегося в состоянии "готов к запуску, но выгружен". Первый процесс, выгруженный из оперативной памяти, переходит в то же состояние. Когда программа подкачки выбирает наиболее подходящий процесс для загрузки в оперативную память, этот процесс переходит в состояние "готовности к запуску в памяти". Планировщик выбирает процесс для исполнения и он переходит в сос- тояние "выполнения в режиме ядра". Когда процесс завершается, он исполняет системную функцию exit, последовательно переходя в состояния "выполнения в режиме ядра" и, наконец, в состояние "прекращения существования". Процесс может управлять некоторыми из переходов на уровне задачи. Во-первых, один процесс может создать другой процесс. Тем не менее, в какое из состояний процесс перейдет после создания (т.е. в состояние "готов к вы- полнению, находясь в памяти" или в состояние "готов к выполнению, но выгру- жен") зависит уже от ядра. Процессу эти состояния не подконтрольны. Во-вто- рых, процесс может обратиться к различным системным функциям, чтобы перейти из состояния "выполнения в режиме задачи" в состояние "выполнения в режиме ядра", а также перейти в режим ядра по своей собственной воле. Тем не менее, момент возвращения из режима ядра от процесса уже не зависит; в результате каких-то событий он может никогда не вернуться из этого режима и из него пе- рейдет в состояние "прекращения существования" (см. раздел 7.2, где говорит- ся о сигналах). Наконец, процесс может завершиться с помощью функции exit по своей собственной воле, но как указывалось ранее, внешние события могут пот- ребовать завершения процесса без явного обращения к функции exit. Все ос- 139 тальные переходы относятся к жестко закрепленной части модели, закодирован- ной в ядре, и являются результатом определенных событий, реагируя на них в соответствии с правилами, сформулированными в этой и последующих главах. Не- которые из правил уже упоминались: например, то, что процесс может выгрузить другой процесс, выполняющийся в ядре. Две принадлежащие ядру структуры данных описывают процесс: запись в таб- лице процессов и пространство процесса. Таблица процессов содержит поля, ко- торые должны быть всегда доступны ядру, а пространство процесса - поля, не- обходимость в которых возникает только у выполняющегося процесса. Поэтому ядро выделяет место для пространства процесса только при создании процесса: в нем нет необходимости, если записи в таблице процессов не соответствует конкретный процесс. Запись в таблице процессов состоит из следующих полей: * Поле состояния, которое идентифицирует состояние процесса. * Поля, используемые ядром при размещении процесса и его пространства в основной или внешней памяти. Ядро использует информацию этих полей для переключения контекста на процесс, когда процесс переходит из состояния "готов к выполнению, находясь в памяти" в состояние "выполнения в режиме ядра" или из состояния "резервирования" в состояние "выполнения в режиме задачи". Кроме того, ядро использует эту информацию при перекачки про- цессов из и в оперативную память (между двумя состояниями "в памяти" и двумя состояниями "выгружен"). Запись в таблице процессов содержит также поле, описывающее размер процесса и позволяющее ядру планировать выделе- ние пространства для процесса. * Несколько пользовательских идентификаторов (UID), устанавливающих раз- личные привилегии процесса. Поля UID, например, описывают совокупность процессов, могущих обмениваться сигналами (см. следующую главу). * Идентификаторы процесса (PID), указывающие взаимосвязь между процессами. Значения полей PID задаются при переходе процесса в состояние "создан" во время выполнения функции fork. * Дескриптор события (устанавливается тогда, когда процесс приостановлен). В данной главе будет рассмотрено использование дескриптора события в ал- горитмах функций sleep и wakeup. * Параметры планирования, позволяющие ядру устанавливать порядок перехода процессов из состояния "выполнения в режиме ядра" в состояние "выполне- ния в режиме задачи". * Поле сигналов, в котором перечисляются сигналы, посланные процессу, но еще не обработанные (раздел 7.2). * Различные таймеры, описывающие время выполнения процесса и использование ресурсов ядра и позволяющие осуществлять слежение за выполнением и вы- числять приоритет планирования процесса. Одно из полей является тайме- ром, который устанавливает пользователь и который необходим для посылки процессу сигнала тревоги (раздел 8.3). Пространство процесса содержит поля, дополнительно характеризующие состояния процесса. В предыдущих главах были рассмотрены последние семь из приводимых ниже полей прост- ранства процесса, которые мы для полноты вновь кратко перечислим: * Указатель на таблицу процессов, который идентифицирует запись, соответс- твующую процессу. * Пользовательские идентификаторы, устанавливающие различные привилегии процесса, в частности, права доступа к файлу (см. раздел 7.6). * Поля таймеров, хранящие время выполнения процесса (и его потомков) в ре- жиме задачи и в режиме ядра. * Вектор, описывающий реакцию процесса на сигналы. * Поле операторского терминала, идентифицирующее "регистрационный терми- нал", который связан с процессом. * Поле ошибок, в которое записываются ошибки, имевшие место при выполнении системной функции. * Поле возвращенного значения, хранящее результат выполнения системной функции. 140 * Параметры ввода-вывода: объем передаваемых данных, адрес источника (или приемника) данных в пространстве задачи, смещения в файле (которыми пользуются операции ввода-вывода) и т.д. * Имена текущего каталога и текущего корня, описывающие файловую систему, в которой выполняется процесс. * Таблица пользовательских дескрипторов файла, которая описывает файлы, открытые процессом. * Поля границ, накладывающие ограничения на размерные характеристики про- цесса и на размер файла, в который процесс может вести запись. * Поле прав доступа, хранящее двоичную маску установок прав доступа к фай- лам, которые создаются процессом. Пространство состояний процесса и пе- реходов между ними рассматривалось в данном разделе на логическом уров- не. Каждое состояние имеет также физические характеристики, управляемые ядром, в частности, виртуальное адресное пространство процесса. Следую- щий раздел посвящен описанию модели распределения памяти; в остальных разделах состояния процесса и переходы между ними рассматриваются на фи- зическом уровне, особое внимание при этом уделяется состояниям "выполне- ния в режиме задачи", "выполнения в режиме ядра", "резервирования" и "приостанова (в памяти)". В следующей главе затрагиваются состояния "создания" и "прекращения существования", а в главе 8 - состояние "го- товности к запуску в памяти". В главе 9 обсуждаются два состояния выгру- женного процесса и организация подкачки по обращению. 6.2 ФОРМАТ ПАМЯТИ СИСТЕМЫ Предположим, что физическая память машины имеет адреса, начиная с 0 и кончая адресом, равным объему памяти в байтах. Как уже отмечалось в главе 2, процесс в системе UNIX состоит из трех логических секций: команд, данных и стека. (Общую память, которая рассматривается в главе 11, можно считать в данном контексте частью секции данных). В секции команд хранится набор ма- шинных инструкций, исполняемых под управлением процесса; адресами в секции команд выступают адреса команд (для команд перехода и обращений к подпрог- раммам), адреса данных (для обращения к глобальным переменным) и адреса сте- ка (для обращения к структурам данных, которые локализованы в подпрограм- мах). Если адреса в сгенерированном коде трактовать как адреса в физической памяти, два процесса не смогут параллельно выполняться, если их адреса пе- рекрываются. Компилятор мог бы генерировать адреса, непересекающиеся у раз- ных программ, но на универсальных ЭВМ такой порядок не практикуется, пос- кольку объем памяти машины ограничен, а количество транслируемых программы неограничено. Даже если для того, чтобы избежать излишнего пересечения адре- сов в процессе их генерации, машина будет использовать некоторый набор эв- ристических процедур, подобная реализация не будет достаточно гибкой и не сможет удовлетворять предъявляемым к ней требованиям. Поэтому компилятор генерирует адреса для виртуального адресного прост- ранства заданного диапазона, а устройство управления памятью, называемое диспетчером памяти, транслирует виртуальные адреса, сгенерированные компиля- тором, в адреса ячеек, расположенных в физической памяти. Компилятору нет необходимости знать, в какое место в памяти ядро потом загрузит выполняемую программу. На самом деле, в памяти одновременно могут существовать несколько копий программы: все они могут выполняться, используя одни и те же виртуаль- ные адреса, фактически же ссылаясь на разные физические ячейки. Те подсисте- мы ядра и аппаратные средства, которые сотрудничают в трансляции виртуальных адресов в физические, образуют подсистему управления памятью. 6.2.1 Области Ядро в версии V делит виртуальное адресное пространство процесса на со- 141 вокупность логических областей. Область - это непрерывная зона виртуального адресного пространства процесса, рассматриваемая в качестве отдельного объ- екта для совместного использования и защиты. Таким образом, команды, данные и стек обычно образуют автономные области, принадлежащие процессу. Несколько процессов могут использовать одну и ту же область. Например, если несколько процессов выполняют одну и ту же программу, вполне естественно, что они ис- пользуют одну и ту же область команд. Точно так же, несколько процессов мо- гут объединиться и использовать общую область разделяемой памяти. Ядро поддерживает таблицу областей и выделяет запись в таблице для каж- дой активной области в системе. В разделе 6.5 описываются поля таблицы об- ластей и операции над областями более подробно, но на данный момент предпо- ложим, что таблица областей содержит информацию, позволяющую определить мес- тоположение области в физической памяти. Каждый процесс имеет частную табли- цу областей процесса. Записи этой таблицы могут располагаться, в зависимости от конкретной реализации, в таблице процессов, в адресном пространстве про- цесса или в отдельной области памяти; для простоты предположим, что они яв- ляются частью таблицы процессов. Каждая запись частной таблицы областей со- держит указатель на соответствующую запись общей таблицы областей и первый виртуальный адрес процесса в данной области. Разделяемые области могут иметь разные виртуальные адреса в каждом процессе. Запись частной таблицы областей также содержит поле прав доступа, в котором указывается тип доступа, разре- шенный процессу: только чтение, только запись или только исполнение. Частная таблица областей и структура области аналогичны таблице файлов и структуре индекса в файловой системе: несколько процессов могут совместно использовать адресное пространство через область, подобно тому, как они разделяют доступ к файлу с помощью индекса; каждый процесс имеет доступ к области благодаря использованию записи в частной таблице областей, точно так же он обращается к индексу, используя соответствующие записи в таблице пользовательских деск- рипторов файла и в таблице файлов, принадлежащей ядру. На Рисунке 6.2 изображены два процесса, A и B, показаны их области, час- тные таблицы областей и виртуальные адреса, в которых эти области соединяют- ся. Процессы разделяют область команд 'a' с виртуальными адресами 8К и 4К соответственно. Если процесс A читает ячейку памяти с адресом 8К, а процесс Частные таблицы областей Области процесса (Виртуальные адреса) +--------+ Коман-+--------------+ | | ды | 8К +-----+ +-->| b | Процесс Дан-+--------------+ | | | | A ные | 16К +-----|---+ +--------+ +--------+ +--------------+ | | | Стек | 32К +-----|-------------------->| c | +--------------+ | +--------+ | | +------>| | +--------+ | a | Коман-+--------------+ +------>| | ды | 4К +-----+ +--------+ +--------+ Процесс Дан-+--------------+ | | B ные | 8К +-------------------------->| e | +--------------+ +--------+ | | Стек | 32К +-----+ | | +--------+ +--------------+ +------>| d | | | +--------+ Рисунок 6.2. Процессы и области 142 B читает ячейку с адресом 4К, то они читают одну и ту же ячейку в области 'a'. Область данных и область стека у каждого процесса свои. Область является понятием, не зависящим от способа реализации управления памятью в операционной системе. Управление памятью представляет собой сово- купность действий, выполняемых ядром с целью повышения эффективности совмес- тного использования оперативной памяти процессами. Примерами способов управ- ления памятью могут служить рассматриваемые в главе 9 замещение страниц па- мяти и подкачка по обращению. Понятие области также не зависит и от собст- венно распределения памяти: например, от того, делится ли память на страницы или на сегменты. С тем, чтобы заложить фундамент для перехода к описанию ал- горитмов подкачки по обращению (глава 9), все приводимые здесь рассуждения относятся, в первую очередь, к организации памяти, базирующейся на страни- цах, однако это не предполагает, что система управления памятью основывается на указанных алгоритмах. 6.2.2 Страницы и таблицы страниц В этом разделе описывается модель организации памяти, которой мы будем пользоваться на протяжении всей книги, но которая не является особенностью системы UNIX. В организации памяти, базирующейся на страницах, физическая память разделяется на блоки одинакового размера, называемые страницами. Обычный размер страниц составляет от 512 байт до 4 Кбайт и определяется кон- фигурацией технических средств. Каждая адресуемая ячейка памяти содержится в некоторой странице и, следовательно, каждая ячейка памяти может адресоваться парой (номер страницы, смещение внутри страницы в байтах). Например, если объем машинной памяти составляет 2 в 32-й степени байт, а размер страницы 1 Кбайт, общее число страниц - 2 в 22-й степени; можно считать, что каждый 32-разрядный адрес состоит из 22-разрядного номера страницы и 10-разрядного смещения внутри страницы (Рисунок 6.3). Когда ядро назначает области физические страницы памяти, необходимости в назначении смежных страниц и вообще в соблюдении какой-либо очередности при назначении не возникает. Целью страничной организации памяти является повы- +------------------------------------------------------------+ | Шестнадцатиричный адрес 58432 | | | | Двоичный 0101 1000 0100 0011 0010 | | | | Номер страницы, смещение | | внутри страницы 01 0110 0001 00 0011 0010 | | | | В шестнадцатиричной системе 161 32 | +------------------------------------------------------------+ Рисунок 6.3. Адресация физической памяти по страницам +------------------------------------------------------+ | Логический номер страницы Физический номер страницы | | | | 0 177 | | 1 54 | | 2 209 | | 3 17 | +------------------------------------------------------+ Рисунок 6.4. Отображение логических номеров страниц на физические 143 шение гибкости назначения физической памяти, которое строится по аналогии с назначением дисковых блоков файлам в файловой системе. Как и при назначении блоков файлу, так и при назначении области страниц памяти, преследуется за- дача повышения гибкости и сокращения неиспользуемого (вследствие фрагмента- ции) пространства памяти. Ядро устанавливает соотношение между виртуальными адресами области и ма- шинными физическими адресами посредством отображения логических номеров страниц в области на физические номера страниц в машине, как это показано на Рисунке 6.4. Поскольку область это непрерывное пространство виртуальных ад- ресов программы, логический номер страницы служит указателем на элемент мас- сива физических номеров страниц. Запись таблицы областей содержит указатель на таблицу физических номеров страниц, именуемую таблицей страниц. Записи таблицы страниц содержат машинно-зависимую информацию, такую как права дос- тупа на чтение или запись страницы. Ядро поддерживает таблицы страниц в па- мяти и обращается к ним так же, как и ко всем остальным структурам данных ядра. На Рисунке 6.5 приведен пример отображения процесса в физические адреса памяти. Пусть размер страницы составляет 1 Кбайт и пусть процессу нужно об- ратиться к объекту в памяти, имеющему виртуальный адрес 68432. Из таблицы областей видно, что виртуальный адрес начала области стека - 65536 (64К), если предположить, что стек растет в направлении увеличения адресов. После вычитания этого адреса из адреса 68432 получаем смещение в байтах внутри об- ласти, равное 2896. Так как каждая страница имеет размер 1 Кбайт, адрес ука- зывает со смещением 848 на 2-ю (начиная с 0) страницу области, расположенной по физическому адресу 986К. В разделе 6.5.5 (где идет речь о загрузке облас- ти) рассматривается случай, когда запись таблицы страниц помечается "пус- той". В современных машинах используются разнообразные аппаратные регистры и кеши, которые повышают скорость выполнения вышеописанной процедуры трансля- ции адресов и без которых пересылки в памяти и адресные вычисления чересчур бы замедлились. Возобновляя выполнение процесса, ядро посредством загрузки соответствующих регистров сообщает техническим средствам управления памятью о том, в Частная таблица областей Таблицы страниц процесса (Физические адреса) +--------------+ Команды | 8К +--------------+ +--------------+ +-------->+--------------+ Данные | 32К +-------+ | пусто | +--------------+ | +--------------+ Стек | 64К +---+ | | 137К | +--------------+ | v +--------------+ Виртуальные адреса | +--------------+ | 852К | | | 87К | +--------------+ +------------+ +--------------+ | 764К | v | 552К | +--------------+ +--------------+ +--------------+ | 433К | | 541К | | 727К | +--------------+ +--------------+ +--------------+ | 333К | | 783К | | 941К | +--------------+ +--------------+ +--------------+ | - | | 986К | | 1096К | | - | +--------------+ +--------------+ | - | | 897К | | 2001К | | - | +--------------+ +--------------+ +--------------+ | - | | - | +--------------+ +--------------+ Рисунок 6.5. Преобразование виртуальных адресов в физические 144 каких физических адресах выполняется процесс и где располагаются таблицы страниц. Поскольку такие операции являются машинно-зависимыми и в разных версиях реализуются по-разному, здесь мы их рассматривать не будем. Часть вопросов, связанных с архитектурой вычислительных систем, затрагивается в упражнениях. Организацию управления памятью попробуем пояснить на следующем простом примере. Пусть память разбита на страницы размером 1 Кбайт каждая, обращение к которым осуществляется через описанные ранее таблицы страниц. Регистры уп- равления памятью в системе группируются по три; первый регистр в тройке со- держит адрес таблицы страниц в физической памяти, второй регистр содержит первый виртуальный адрес, отображаемый с помощью тройки регистров, третий регистр содержит управляющую информацию, такую как номера страниц в таблице страниц и права доступа к страницам (только чтение, чтение и запись). Такая модель соответствует вышеописанной модели области. Когда ядро готовит про- цесс к выполнению, оно загружает тройки регистров соответствующей информаци- ей из записей частной таблицы областей процесса. Если процесс обращается к ячейкам памяти, расположенным за пределами принадлежащего ему виртуального пространства, создается исключительная ситу- ация. Например, если область команд имеет размер 16 Кбайт (Рисунок 6.5), а процесс обращается к виртуальному адресу 26К, создается исключительная ситу- ация, обрабатываемая операционной системой. То же самое происходит, если процесс пытается обратиться к памяти, не имея соответствующих прав доступа, например, пытается записать адрес в защищенную от записи область команд. И в том, и в другом примере процесс обычно завершается (более подробно об этом в следующей главе). 6.2.3 Размещение ядра Несмотря на то, что ядро работает в контексте процесса, отображение вир- туальных адресов, связанных с ядром, осуществляется независимо от всех про- цессов. Программы и структуры данных ядра резидентны в системе и совместно используются всеми процессами. При запуске системы происходит загрузка прог- рамм ядра в память с установкой соответствующих таблиц и регистров для отоб- ражения виртуальных адресов ядра в физические. Таблицы страниц для ядра име- ют структуру, аналогичную структуре таблицы страниц, связанной с процессом, а механизмы отображения виртуальных адресов ядра похожи на механизмы, ис- пользуемые для отображения пользовательских адресов. На многих машинах вир- туальное адресное пространство процесса разбивается на несколько классов, в том числе системный и пользовательский, и каждый класс имеет свои собствен- ные таблицы страниц. При работе в режиме ядра система разрешает доступ к ад- ресам ядра, при работе же в режиме задачи такого рода доступ запрещен. Поэ- тому, когда в результате прерывания или выполнения системной функции проис- ходит переход из режима задачи в режим ядра, операционная система по догово- ренности с техническими средствами разрешает ссылки на адреса ядра, а при возврате в режим ядра эти ссылки уже запрещены. В других машинах можно ме- нять преобразование виртуальных адресов, загружая специальные регистры во время работы в режиме ядра. На Рисунке 6.6 приведен пример, в котором виртуальные адреса от 0 до 4М-1 принадлежат ядру, а начиная с 4М - процессу. Имеются две группы регист- ров управления памятью, одна для адресов ядра и одна для адресов процесса, причем каждой группе соответствует таблица страниц, хранящая номера физичес- ких страниц со ссылкой на адреса виртуальных страниц. Адресные ссылки с ис- пользованием группы регистров ядра допускаются системой только в режиме яд- ра; следовательно, для перехода между режимом ядра и режимом задачи требует- ся только, чтобы система разрешила или запретила адресные ссылки с использо- 145 ванием группы регистров ядра. В некоторых системах ядро загружается в память таким образом, что боль- шая часть виртуальных адресов ядра совпадает с физическими адресами и функ- ция преобразования виртуальных адресов в физические превращается в функцию тождественности. Работа с пространством процесса, тем не менее, требует, чтобы преобразование виртуальных адресов в физические производилось ядром. Адрес таблицы Вирту- Номера стра- страниц альный ниц в табли- адрес це +-----------+------------+-----------+ Регистр ядра 1 | --------+ 0 | | +-----------+-|----------+-----------+ Регистр ядра 2 | ---+ | | 1М | | +--------|--+-|----------+-----------+ Регистр ядра 3 | --+| | | 2М | | +-------||--+-|----------+-----------+ Регистр процесса 1 | +--- || | | 4М | | +-|-----||--+-|----------+-----------+ Регистр процесса 2 | |+-- || | | | | +-||----||--+-|----------+-----------+ Регистр процесса 3 | ||+- || | | | | +-|||---||--+-|----------+-----------+ +------------------------+|| || | | +--------------+| |+----|-------+ | | +----+ +-----|-------|----------+ | | | +--+ | | v v v v v v +------+ +------+ +------+ +------+ +------+ +------+ | 856K | | 747K | | 556K | | 0K | | 128K | | 256K | +------+ +------+ +------+ +------+ +------+ +------+ | 917K | | 950K | | 997K | | 4K | | 97K | | 292K | +------+ +------+ +------+ +------+ +------+ +------+ | 564K | | 333K | | 458K | | 3K | | 135K | | 304K | +------+ +------+ +------+ +------+ +------+ +------+ | 444K | | - | | 632K | | 17K | | 139K | | 279K | +------+ | - | +------+ +------+ +------+ +------+ | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | +------+ +------+ +------+ +------+ +------+ +------+ Таблицы страниц процесса Таблицы страниц ядра (области) Рисунок 6.6. Переключение режима работы с непривилегированного (режима задачи) на привилегированный (режим ядра) 6.2.4 Пространство процесса Каждый процесс имеет свое собственное пространство, однако ядро обраща- ется к пространству выполняющегося процесса так, как если бы в системе оно было единственным. Ядро подбирает для текущего процесса карту трансляции виртуальных адресов, необходимую для работы с пространством процесса. При компиляции загрузчик назначает переменной 'u' (имени пространства процесса) фиксированный виртуальный адрес. Этот адрес известен остальным компонентам ядра, в частности модулю, выполняющему переключение контекста (раздел 6.4.3). Ядру также известно, какие таблицы управления памятью используются 146 при трансляции виртуальных адресов, принадлежащих пространству процесса, и благодаря этому ядро может быстро перетранслировать виртуальный адрес прост- ранства процесса в другой физический адрес. По одному и тому же виртуальному адресу ядро может получить доступ к двум разным физическим адресам, описыва- ющим пространства двух процессов. Процесс имеет доступ к своему пространству, когда выполняется в режиме ядра, но не тогда, когда выполняется в режиме задачи. Поскольку ядро в каж- дый момент времени работает только с одним пространством процесса, используя для доступа виртуальный адрес, пространство процесса частично описывает кон- текст процесса, выполняющегося в системе. Когда ядро выбирает процесс для исполнения, оно ищет в физической памяти соответствующее процессу пространс- тво и делает его доступным по виртуальному адресу. Адрес таблицы Вирту- Номера стра- страниц альный ниц в табли- адрес це +-----------+------------+-----------+ Регистр ядра 1 | | | | +-----------+------------+-----------+ Регистр ядра 2 | | | | +-----------+------------+-----------+ (Прост- Регистр ядра 3 | ---+ | 2M | 4 | ранство +--------|--+------------+-----------+ процесса) | +---------------------+ | Таблицы страниц для пространства процессов | v +------+ +------+ +------+ +------+ | 114K | | 843K | |1879K | | 184K | +------+ +------+ +------+ +------+ | 708K | | 794K | | 290K | | 176K | +------+ +------+ +------+ +------+ | 143K | | 361K | | 450K | | 209K | +------+ +------+ +------+ +------+ | 565K | | 847K | | 770K | | 477K | +------+ +------+ +------+ +------+ Процесс A Процесс B Процесс C Процесс D Рисунок 6.7. Карта памяти пространства процесса в ядре Предположим, например, что пространство процесса имеет размер 4 Кбайта и помещается по виртуальному адресу 2М. На Рисунке 6.7 показана карта памяти, где первые два регистра из группы относятся к программам и данным ядра (ад- реса и указатели не показаны), а третий регистр адресует к пространству про- цесса D. Если ядру нужно обратиться к пространству процесса A, оно копирует связанную с этим пространством информацию из соответствующей таблицы страниц в третий регистр. В любой момент третий регистр ядра описывает пространство текущего процесса, но ядро может сослаться на пространство другого процесса, переписав записи в таблице страниц с новым адресом. Информация в регистрах 1 и 2 для ядра неизменна, поскольку все процессы совместно используют програм- мы и данные ядра. 6.3 КОНТЕКСТ ПРОЦЕССА Контекст процесса включает в себя содержимое адресного пространства за- дачи, выделенного процессу, а также содержимое относящихся к процессу аппа- 147 ратных регистров и структур данных ядра. С формальной точки зрения, контекст процесса объединяет в себе пользовательский контекст, регистровый контекст и системный контекст (*