2 | 2 | 2 | 2 2| выгружен | выгружен | загружен | загружен | | 0 | 0 | 0 | 0 | | | | запущен | | | | | | | | | | | | --+- 1 | 1 | 1 | 1 | 3 3| | | | запущен | | | | | | | | | | | | | | | | | | | | | --+- 2 | 2 | 2 | 2 | 4 4| загружен | | выгружен | выгружен | загружен | 0 | | 0 | 0 | 0 | | | | | запущен | | | | | | | | | | --+- 1 | 3 | 1 | 1 | 1 5| запущен | | | | | | | | | | | | | | | | | | | | | | | | --+- 2 | 4 | 2 | 2 | 2 6| выгружен | загружен | загружен | | выгружен | 0 | 0 | 0 | | 0 | | запущен | | | | | | | | v Рисунок 9.10. Последовательность операций, выполняемых процессом подкачки 264 Время Процесс A B C D E --+--------------+-----------+-----------+-----------+----------- 0| 0 | 0 | выгружен | nice 25 | выгружен | запущен | | 0 | выгружен | 0 | | | | 0 | | | | | | | | | | | | | | | | --+- 1 | 1 | 1 | 1 | 1 1| | запущен | | | | | | | | | | | | | | | | | | | | | | | --+- 2 | 2 | 2 | 2 | 2 2| выгружен | выгружен | загружен | загружен | | 0 | 0 | 0 | 0 | | | | запущен | | | | | | | | | | | | --+- 1 | 1 | 1 | 1 | 3 3| | | | выгружен | загружен | | | | 0 | 0 | | | | | запущен | | | | | | | | | | --+- 2 | 2 | 2 | 1 | 1 4| загружен | | выгружен | | | 0 | | 0 | | | запущен | | | | | | | | | | | | | | --+- 1 | 3 | 1 | 2 | 2 5| | загружен | | | выгружен | | 0 | | | 0 | | запущен | | | | | | | | | | | | | --+- 2 | 1 | 2 | 3 | 1 6| выгружен | | | загружен | | 0 | | | 0 | | | | | запущен | | | | | | v Рисунок 9.11. Загрузка процессов в случае разбивки временных интервалов на части памяти находятся в состоянии приостанова, все готовые к выполнению процессы выгружены, для новых процессов на устройстве выгрузки уже нет места, нет свободного места и в основной памяти. Эта ситуация разбирается в упражнении 9.5. Интерес к проблемам, связанным с подкачкой процессов, в последние годы спал в связи с реализацией алгоритмов подкачки страниц памяти. 265 9.2 ПОДКАЧКА ПО ЗАПРОСУ Алгоритм подкачки страниц памяти поддерживается на машинах со страничной организацией памяти и с ЦП, имеющим прерываемые команды (***). В системах с подкачкой страниц отсутствуют ограничения на размер процесса, связанные с объемом доступной физической памяти. Например, в машинах с объемом физичес- кой памяти 1 и 2 Мбайта могут исполняться процессы размером 4 или 5 Мбайт. Ограничение на виртуальный размер процесса, связанное с объемом адресуемой виртуальной памяти, остается в силе и здесь. Поскольку процесс может не по- меститься в физической памяти, ядру приходится динамически загружать в па- мять отдельные его части и исполнять их, несмотря на отсутствие остальных частей. В механизме подкачки страниц все открыто для пользовательских прог- рамм, за исключением разрешенного процессу виртуального размера. Процессы стремятся исполнять команды небольшими порциями, которые имену- ются программными циклами или подпрограммами, используемые ими указатели группируются в небольшие поднаборы, располагаемые в информационном простран- стве процесса. В этом состоит суть так называемого принципа "локальности". Деннингом [Denning 68] было сформулировано понятие рабочего множества про- цесса как совокупности страниц, использованных процессом в последних n ссыл- ках на адресное пространство памяти; число n называется окном рабочего мно- жества. Поскольку рабочее множество процесса является частью от целого, в основной памяти может поместиться больше процессов по сравнению с теми сис- темами, где управление памятью базируется на подкачке процессов, что в ко- нечном итоге приводит к увеличению производительности системы. Когда процесс обращается к странице, отсутствующей в его рабочем множестве, возникает ошибка, при обработке которой ядро корректирует рабочее множество процесса, в случае необходимости подкачивая страницы с внешнего устройства. На Рисунке 9.12 приведена последовательность используемых процессом ука- зателей страниц, описывающих рабочие множества с окнами различных размеров при условии соблюдения алгоритма замещения "стариков" (замещения страниц пу- тем откачки тех, к которым наиболее долго не было обращений). По мере выпол- нения процесса его рабочее множество видоизменяется в соответствии с исполь- зуемыми процессом указателями страниц; увеличение размера окна влечет за со- бой увеличение рабочего множества и, с другой стороны, сокращение числа оши- бок в выполнении процесса. Использование неизменного рабочего множества не практикуется, поскольку запоминание очередности следования указателей стра- ниц потребовало бы слишком больших затрат. Приблизительное соответствие меж- ду изменяемым рабочим множеством и пространством процесса достигается путем установки бита упоминания (reference bit) при обращении к странице памяти, а также периодическим опросом указателей страниц. Если на страницу была сдела- на ссылка, эта страница включается в рабочее множество; в противном случае она "дозревает" в памяти в ожидании своей очереди. В случае возникновения ошибки из-за обращения к странице, отсутствующей в рабочем множестве, ядро приостанавливает выполнение процесса до тех пор, пока страница не будет считана в память и не станет доступной процессу. Ког- да страница будет загружена, процесс перезапустит ту команду, на которой вы- полнение процесса было приостановлено из-за ошибки. Таким образом, работа подсистемы замещения страниц распадается на две части: откачка редко исполь- зуемых страниц на устройство выгрузки и обработка ошибок из-за отсутствия нужной страницы. Такое общее толкование механизма замещения страниц, конечно же, выходит за пределы одной конкретной системы. Оставшуюся часть главы мы посвятим более детальному рассмотрению особенностей реализации этого меха- низма в версии V системы UNIX. --------------------------------------- (***) Если при исполнении команды возникает ошибка, связанная с отсутствием страницы, после обработки ошибки ЦП обязан перезапустить команду, пос- кольку промежуточные результаты, полученные к моменту возникновения ошибки, могут быть утрачены. 266 9.2.1 Структуры данных, используемые подсистемой замещения страниц Для поддержки функций управления памятью на машинном (низком) уровне и для реализации механизма замещения страниц ядро использует 4 основные струк- туры данных: записи таблицы страниц, дескрипторы дисковых блоков, таблицу содержимого страничных блоков (page frame data table - сокращенно: pfdata) и таблицу использования области подкачки. Место для таблицы pfdata выделяется один раз на все время жизни системы, для других же структур страницы памяти выделяются динамически. Из главы 6 нам известно, что каждая область располагает своими таблицами страниц, с помощью которых осуществляется доступ к физической памяти. Каждая запись таблицы страниц (Рисунок 9.13) состоит из физического адреса страни- цы, кода защиты, в разрядах которого описываются права доступа процесса к странице (на чтение, запись и исполнение), а также следующих двоичных полей, используемых механизмом замещения страниц: Последователь- ность указате- Рабочие множества Размеры окон лей страниц 2 3 4 5 +------------+ +-------+----------+-------------+----------------+ | 24 | | 24 | 24 | 24 | 24 | +------------+ | | | | | | 15 | | 15 24 | 15 24 | 15 24 | 15 24 | +------------+ | | | | | | 18 | | 18 15 | 18 15 24 | 18 15 24 | 18 15 24 | +------------+ | | | | | | 23 | | 23 18 | 23 18 15 | 23 18 15 24 | 23 18 15 24 | +------------+ | | | - | - | | 24 | | 24 23 | 24 23 18 | - | - | +------------+ | | | - | - | | 17 | | 17 24 | 17 24 23 | 17 24 23 18 | 17 24 23 18 15 | +------------+ | | | - | - | | 18 | | 18 17 | 18 17 24 | - | - | +------------+ | | - | - | - | | 24 | | 24 18 | - | - | - | +------------+ | | - | - | - | | 18 | | 18 24 | - | - | - | +------------+ | | - | - | - | | 17 | | 17 18 | - | - | - | +------------+ | | - | - | - | | 17 | | | - | - | - | +------------+ | | - | - | - | | 15 | | 15 17 | 15 17 18 | 15 17 18 24 | - | +------------+ | | | - | - | | 24 | | 24 15 | 24 15 17 | - | - | +------------+ | | - | - | - | | 17 | | 17 24 | - | - | - | +------------+ | | - | - | - | | 24 | | 24 17 | - | - | - | +------------+ | | - | - | - | | 18 | | 18 24 | 18 24 17 | - | - | +------------+ +-------+----------+-------------+----------------+ Рисунок 9.12. Рабочее множество процесса * бит доступности * бит упоминания 267 * бит модификации * бит копирования при записи * "возраст" страницы Установка бита доступности свидетельствует о правильности содержимого страницы памяти, однако из того, что бит доступности выключен, не следует с необходимостью то, что ссылка на страницу недопустима, в чем мы убедимся позже. Бит упоминания устанавливается в том случае, если процесс делает ссылку на страницу, а бит модификации - в том случае, если процесс скоррек- тировал содержимое страницы. Установка бита копирования при записи, произво- димая во время выполнения системной функции fork, свидетельствует о том, что ядру в случае, когда процесс корректирует содержимое страницы, следует соз- давать ее новую копию. Наконец, "возраст" страницы говорит о продолжитель- ности ее пребывания в составе рабочего множества процесса. Биты доступности, копирования при записи и "возраст" страницы устанавливаются ядром, биты упо- минания и модификации - аппаратным путем; в разделе 9.2.4 рассматриваются конфигурации, в которых эти возможности не поддерживаются аппаратурой. +--------+ +->+----------------------+---------------------------+ | | | | | | | | | +----------------------+---------------------------+ | | | | | | | | | +----------------------+---------------------------+ | Область| | | | | | | | +----------------------+---------------------------+ | | | |Записи таблицы страниц|Дескрипторы дисковых блоков| | ----+-+ +----------------------+---------------------------+ | | | | | | | +----------------------+---------------------------+ | | | | | +--------+ +----------------------+---------------------------+ | | | +----------------------+---------------------------+ | | | +----------------------+---------------------------+ | | | +----------------------+---------------------------+ | | | +----------------------+---------------------------+ Запись таблицы страниц +-----------------------------+-------+-----+-----+----+-----+---+ | Адрес страницы (физический) |Возраст|Копи-|Моди-|Упо-|До- |За-| | | |рова-|фика-|ми- |пус- |щи-| | | |ние |ция |на- |ти- |та | | | |при | |ние |мость| | | | |запи-| | | | | | | |си | | | | | +-----------------------------+-------+-----+-----+----+-----+---+ Дескриптор дискового блока +-----------------------+---------------+------------------------+ | Устройство выгрузки | Номер блока | Тип (находится на ус- | | | | тройстве выгрузки, в | | | | файле, при обращении | | | | обнуляется, заполняет- | | | | ся) | +-----------------------+---------------+------------------------+ Рисунок 9.13. Записи таблицы страниц и дескрипторы дисковых блоков 268 Каждая запись таблицы страниц связана с дескриптором дискового блока, описывающим дисковую копию виртуальной страницы (Рисунок 9.13). Поэтому про- цессы, использующие разделяемую область, обращаются к общим записям таблицы страниц и к одним и тем же дескрипторам дисковых блоков. Содержимое вирту- альной страницы располагается либо в отдельном блоке на устройстве выгрузки, либо в исполняемом файле, либо вообще отсутствует на устройстве выгрузки. Если страница находится на устройстве выгрузки, в дескрипторе дискового бло- ка содержится логический номер устройства и номер блока, по которым можно отыскать содержимое страницы. Если страница содержится в исполняемом файле, в дескрипторе дискового блока располагается номер логического блока в файле с содержимым страницы; ядро может быстро преобразовать этот номер в адрес на диске. В дескрипторе дискового блока также имеется информация о двух уста- навливаемых функцией exec особых условиях: страница при обращении к ней за- полняется ("demand fill") или обнуляется ("demand zero"). Разъяснения по этому поводу даются в разделе 9.2.1.2. В таблице pfdata описывается каждая страница физической памяти. Записи таблицы проиндексированы по номеру страницы и состоят из следующих полей: * Статус страницы, указывающий на то, что страница располагается на уст- ройстве выгрузки или в исполняемом файле, что к странице произведено об- ращение по прямому доступу в память (путем считывания информации с уст- ройства выгрузки), или на то, что страница может быть переназначена. * Количество процессов, ссылающихся на страницу. Счетчик ссылок хранит число записей в таблице страниц, имеющих ссылку на текущую страницу. Это значение может отличаться от количества процессов, использующих разделя- емую область с данной страницей, в чем мы убедимся чуть позже, когда бу- дем снова обращаться к алгоритму функции fork. * Логический номер устройства (устройства выгрузки или файловой системы) и номер блока, указывающие расположение содержимого страницы. * Указатели на другие записи таблицы pfdata в соответствии со списком сво- бодных страниц или с хеш-очередью страниц. По аналогии с буферным кешем ядро связывает записи таблицы pfdata в спи- сок свободных страниц и хеш-очередь. Список свободных страниц представляет собой буфер, который содержит страницы, доступные для переназначения, однако процесс, обратившийся к этим страницам, может столкнуться с ошибкой адреса- ции, так и не получив соответствующую страницу из списка. Этот список дает ядру возможность сократить число операций чтения с устройства выгрузки. Ядро выделяет страницы из этого списка по вышеназванному принципу замещения "ста- риков". Ядро выстраивает записи таблицы в хеш-очередь в соответствии с номе- ром устройства (выгрузки) и номером блока. Используя эти номера, ядро может быстро отыскать страницу, если она находится в памяти. Передавая физическую страницу области, ядро выбирает соответствующую запись из списка свободных страниц, исправляет указанные в ней номера устройства и блока и помещает ее в соответствующее место хеш-очереди. Каждая запись таблицы использования области подкачки соответствует стра- нице, находящейся на устройстве выгрузки. Запись содержит счетчик ссылок, показывающий количество записей таблицы страниц, в которых имеется ссылка на текущую страницу. На Рисунке 9.14 показана взаимосвязь между записями таблицы страниц, дескрипторами дисковых блоков, записями таблицы pfdata и таблицы использова- ния области подкачки. Виртуальный адрес 1493К отображается на запись таблицы страниц, соответствующую странице с физическим номером 794; дескриптор дис- кового блока, связанный с этой записью, свидетельствует о том, что содержи- мое страницы располагается на устройстве выгрузки с номером 1 в дисковом блоке с номером 2743. Запись таблицы pfdata, помимо того, что указывает на те же номера устройства и блока, сообщает, что счетчик ссылок на физическую страницу имеет значение, равное 1. О том, почему номер дискового блока дуб- лируется в записи таблицы pfdata, вы узнаете из раздела 9.2.4.1. Счетчик ссылок на виртуальную страницу (в записи таблицы использования области под- качки) свидетельствует о том, что на копию страницы на устройстве выгрузки 269 ссылается только одна запись таблицы страниц. 9.2.1.1 Функция fork в системе с замещением страниц Как уже говорилось в разделе 7.1, во время выполнения функции fork ядро создает копию каждой области родительского процесса и присоединяет ее к про- цессу-потомку. В системе с замещением стра- +-----------------------+--------------------------+ Виртуальный |Запись таблицы страниц|Дескриптор дискового блока| адрес +-----------------------+--------------------------+ 1493К | Номер страницы 794 | Устройство 1 Блок 2743 | +---+-+-----------------+--------------------+-----+ | | | | | Запись таблицы pfdata, | | | соответствующая стра- +------------+ +------------+ v нице с номером 794 | | +------------+-----------------------+ | | | | Счетчик ссылок 1 | | Запись таблицы | | +-----------------------+ | использования | | | Номер устройства 1 | | области подкачки | | +-----------------------+ | +-----------------+ | | | Номер блока 2743 | | |Счетчик ссылок 1| | | +-----------------+-----+ | +--------+--------+ | | | +-----+ | | | | | +--------------+ v v v v v +--------------------------+ +---------------------------+ | Физическая страница 794 | | Номер блока 2743 | +--------------------------+ +---------------------------+ Рисунок 9.14. Взаимосвязь между структурами данных, участвующими в реа- лизации механизма замещения страниц по обращению ниц ядро по традиции создает физическую копию адресного пространства процес- са-родителя, что в общем случае является довольно расточительной операцией, поскольку процесс часто после выполнения функции fork обращается к функции exec и незамедлительно освобождает только что скопированное пространство. Если область разделяемая, в версии V вместо копирования страницы ядро просто увеличивает значение счетчика ссылок на область (в таблице областей, в таб- лице страниц и в таблице pfdata). Тем не менее, для частных областей, таких как область данных и стека, ядро отводит в таблице областей и таблице стра- ниц новую запись, после чего просматривает в таблице страниц все записи про- цесса-родителя: если запись верна, ядро увеличивает значение счетчика ссылок в таблице pfdata, отражающее количество процессов, использующих страницу че- рез разные области (в отличие от тех процессов, которые используют данную страницу через разделяемую область). Если страница располагается на устройс- тве выгрузки, ядро увеличивает значение счетчика ссылок в таблице использо- вания области подкачки. Теперь на страницу могут ссылаться обе области, использующие эту страни- цу совместно, пока процесс не ведет на нее запись. Как только страница пона- добится процессу для записи, ядро создаст ее копию, с тем, чтобы у каждой области была своя личная версия страницы. Для этого при выполнении функции fork в каждой записи таблицы страниц, соответствующей частным областям роди- теля и потомка, ядро устанавливает бит "копирования при записи". Если один из процессов попытается что-то записать на страницу, он получит отказ систе- мы защиты, после чего для него будет создана новая копия содержимого страни- цы. Таким образом, физическое копирование страницы откладывается до того мо- 270 мента, когда в этом возникнет реальная потребность. В качестве примера рассмотрим Рисунок 9.15. Процессы разделяют доступ к таблице страниц совместно используемой области команд T, поэтому значение счетчика ссылок на область равно 2, а на страницы области единице (в таблице pfdata). Ядро назначает про- Процесс-родитель Процесс-потомок Частная таблица Частная таблица областей процесса областей процесса +--------------+ +--------------+ | - | | - | +--------------+ +--------------+ | - - | | - - | +--------------+ +--------------+ - + ---------------------+ - - - - - v v v v +-------------------+ +-------------------+ +-------------------+ | Область T | | Область P1 | | Область C1 | | Счетчик ссылок 2 | | Счетчик ссылок 1 | | Счетчик ссылок 1 | |+-----------------+| |+-----------------+| |+-----------------+| || Записи таблицы || || Записи таблицы || || Записи таблицы || || страниц || || страниц || || страниц || |+-----------------+| |+-----------------+| |+-----------------+| || - || || - || || - || || - || || - || || - || |+-----------------+| || - || || - || ||Виртуаль- Стра-|| || - || || - || ||ный адрес ница || || - || || - || || 24К 967 || || - || || - || |+-----------------+| |+-----------------+| |+-----------------+| || - - || ||Виртуаль- Стра-|| ||Виртуаль- Стра-|| || - - || ||ный адрес ница || ||ный адрес ница || || - - || || 97К 613 || || 97К 613 || || - - || |+-----------------+| |+-----------------+| || - - || || - - || || - - || || - - || || - - || || - - || |+-----------------+| |+-----------------+| |+-----------------+| +-------------------+ +-------------------+ +-------------------+ - - ----------- v v v +---------------------+ +---------------------+ | Страничный блок 967 | | Страничный блок 613 | | Счетчик ссылок 1 | | Счетчик ссылок 2 | +---------------------+ +---------------------+ Рисунок 9.15. Адресация страниц, участвующих в процессе вы- полнения функции fork цессу-потомку новую область данных C1, являющуюся копией области P1 процес- са-родителя. Обе области используют одни и те же записи таблицы страниц, это видно на примере страницы с виртуальным адресом 97К. Этой странице в таблице pfdata соответствует запись с номером 613, счетчик ссылок в которой равен 2, ибо на страницу ссылаются две области. В ходе выполнения функции fork в системе BSD создается физическая копия страниц родительского процесса. Однако, учитывая наличие ситуаций, в которых создание физической копии не является обязательным, в системе BSD существует 271 также функция vfork, которая используется в том случае, если процесс сразу по завершении функции fork собирается запустить функцию exec. Функция vfork не копирует таблицы страниц, поэтому она работает быстрее, чем функция fork в версии V системы UNIX. Однако процесс-потомок при этом исполняется в тех же самых физических адресах, что и его родитель, и может поэтому затереть данные и стек родительского процесса. Если программист использует функцию vfork неверно, может возникнуть опасная ситуация, поэтому вся ответствен- ность за ее использование возлагается на программиста. Различие в подходах к рассматриваемому вопросу в системах UNIX и BSD имеет философский характер, они дают разный ответ на один и тот же вопрос: следует ли ядру скрывать осо- бенности реализации своих функций, превращая их в тайну для пользователей, или же стоит дать опытным пользователям возможность повысить эффективность выполнения системных операций ? +------------------------------------------------------------+ | int global; | | main() | | { | | int local; | | | | local = 1; | | if (vfork() == 0) | | { | | /* потомок */ | | global = 2; /* запись в область данных родителя */| | local = 3; /* запись в стек родителя */ | | _exit(); | | } | | printf("global %d local %d\n",global,local); | | } | +------------------------------------------------------------+ Рисунок 9.16. Функция vfork и искажение информации процесса В качестве примера рассмотрим программу, приведенную на Рисунке 9.16. После выполнения функции vfork процесс-потомок не запускает функцию exec, а переустанавливает значения переменных global и local и завершается (****). Система гарантирует, что процесс-родитель приостанавливается до того момен- та, когда потомок исполнит функции exec или exit. Возобновив в конечном ито- ге свое выполнение, процесс-родитель обнаружит, что значения двух его пере- менных не совпадают с теми значениями, которые были у них до обращения к функции vfork ! Еще больший эффект может произвести возвращение процесса-по- томка из функции, вызвавшей функцию vfork (см. упражнение 9.8). 9.2.1.2 Функция exec в системе с замещением страниц Как уже говорилось в главе 7, когда процесс обращается к системной функ- ции exec, ядро считывает из файловой системы в память указанный исполняемый файл. Однако в системе с замещением страниц по запросу исполняемый файл, --------------------------------------- (****) Функция exit используется в варианте _exit, потому что она "очищает" структуры данных, передаваемые через стандартный ввод-вывод (на поль- зовательском уровне), для обоих процессов, так что оператор printf, используемый родителем, не даст правильный результат - еще один неже- лательный побочный эффект от применения функции vfork. 272 имеющий большой размер, может не уместиться в доступном пространстве основ- ной памяти. Поэтому ядро не назначает ему сразу все пространство, а отводит место в памяти по мере надобности. Сначала ядро назначает файлу таблицы страниц и дескрипторы дисковых блоков, помечая страницы в записях таблиц как "заполняемые при обращении" (для всех данных, кроме имеющих тип bss) или "обнуляемые при обращении" (для данных типа bss). Считывая в память каждую страницу файла по алгоритму read, процесс получает ошибку из-за отсутствия (недоступности) данных. Подпрограмма обработки ошибок проверяет, является ли страница "заполняемой при обращении" (тогда ее содержимое будет немедленно затираться содержимым исполняемого файла и поэтому ее не надо очищать) или "обнуляемой при обращении" (тогда ее следует очистить). В разделе 9.2.3 мы увидим, как это происходит. Если процесс не может поместиться в памяти, "сборщик" страниц освобождает для него место, периодически откачивая из па- мяти неиспользуемые страницы. В этой схеме видны явные недостатки. Во-первых, при чтении каждой стра- ницы исполняемого файла процесс сталкивается с ошибкой из-за обращения к от- сутствующей странице, пусть даже процесс никогда и не обращался к ней. Во-вторых, если после того, как "сборщик" страниц откачал часть страниц из памяти, была запущена функция exec, каждая только что выгруженная и вновь понадобившаяся страница потребует дополнительную операцию по ее загрузке. Чтобы повысить эффективность функции exec, ядро может востребовать страницу непосредственно из исполняемого файла, если данные в файле соответствующим образом настроены, что определяется значением т.н. "магического числа". Од- нако, использование стандартных алгоритмов доступа к файлу (например, bmap) потребовало бы при обращении к странице, состоящей из блоков косвенной адре- сации, больших затрат, связанных с многократным использованием буферного ке- ша для чтения каждого блока. Кроме того, функция bmap не является реентера- бельной, отсюда возникает опасность нарушения целостности данных. Во время выполнения системной функции read ядро устанавливает в пространстве процесса значения различных параметров ввода-вывода. Если при попытке скопировать данные в пространство пользователя процесс столкнется с отсутствием нужной страницы, он, считывая страницу из файловой системы, может затереть содержа- щие эти параметры поля. Поэтому ядро не может прибегать к использованию обычных алгоритмов обработки ошибок данного рода. Конечно же алгоритмы долж- ны быть в обычных случаях реентерабельными, поскольку у каждого процесса свое отдельное адресное пространство и процесс не может одновременно испол- нять несколько системных функций. Для того, чтобы считывать страницы непосредственно из исполняемого фай- ла, ядро во время исполнения функции exec составляет список номеров дисковых блоков файла и присоединяет этот список к индексу файла. Работая с таблицами страниц такого файла, ядро находит дескриптор дискового блока, содержащего страницу, и запоминает номер блока внутри файла; этот номер позже использу- Список блоков, Область +-> связанный с индексом +---------------------------------+ | +----------------+ | Индекс-----------+-+ 0 | | | | - | | | | - | | | Дескриптор дискового блока | - | | | +---------------------------+ | - | | | | Логический блок 84 | | - +----------------+ | +---------------------------+ | 84 | 279 | | | +----------------+ +---------------------------------+ | | | | +----------------+ Рисунок 9.17. Отображение файла на область 273 ется при загрузке страницы из файла. На Рисунке 9.17 показан пример, в кото- ром страница имеет адрес расположения в логическом блоке с номером 84 от на- чала файла. В области имеется указатель на индекс, в котором содержится но- мер соответствующего физического блока на диске (279). 9.2.2 "Сборщик" страниц "Сборщик" страниц (page stealer) является процессом, принадлежащим ядру операционной системы и выполняющим выгрузку из памяти тех страниц, которые больше не входят в состав рабочего множества пользовательского процесса. Этот процесс создается ядром во время инициализации системы и запускается в любой момент, когда в нем возникает необходимость. Он просматривает все ак- тивные незаблокированные области и увеличивает значение "возраста" каждой принадлежащей им страницы (заблокированные области пропускаются, но впослед- ствии, по снятии блокировки, тоже будут учтены). Когда процесс при работе со страницей, принадлежащей области, получает ошибку, ядро блокирует область, чтобы "сборщик" не смог выгрузить страницу до тех пор, пока ошибка не будет обработана. Страница в памяти может находиться в двух состояниях: либо "дозревать", не будучи еще готовой к выгрузке, либо быть готовой к выгрузке и доступной для привязки к другим виртуальным страницам. Первое состояние означает, что процесс обратился к странице и поэтому страница включена в его рабочее мно- жество. При обращении к странице в некоторых машинах аппаратно устанавлива- ется бит упоминания, если же эта операция не выполняется, соответственно, и программные методы скорее всего используются другие (раздел 9.2.4). Если страница находится в первом состоянии, "сборщик" сбрасывает бит упоминания в ноль, но запоминает количество просмотров множества страниц, выполненных с момента последнего обращения к странице со стороны пользовательского процес- са. Таким образом, первое состояние распадается на несколько подсостояний в соответствии с тем, сколько раз "сборщик" страниц обратился к странице до того, как страница стала готовой для выгрузки (см. Рисунок 9.18). Когда это число превышает некоторое пороговое значение, ядро переводит страницу во второе состояние - состояние готовности к выгрузке. Максимальная продолжи- тельность пребывания страницы в первом состоянии зависит от условий конкрет- ной реализации и ограничивается числом отведенных для этого поля разрядов в записи таблицы страниц. На Рисунке 9.19 показано взаимодействие между процессами, работающими со страницей, и "сборщиком" страниц. Цифры обозначают номер обращения "сборщи- Ссылка на страницу +------------+----------+----------+-----------------+ | ^ ^ ^ | v | | | | Готов- +-------+ | | | | ность | Стра- | +-+-+ +-+-+ +-+-+ +-+-+ к | ница в|----->| 1 +----->| 2 +----->| 3 +----­­­­---->| n | вы- | памяти| +---+ +---+ +---+ +-+-+ груз- +-------+ "Дозревание" страницы --- отсутствие | ке ^ ссылок | | | | +--------+ | | | Страни-| | За- +-----------------------| ца вы- |<------------------+ Выгруз- грузка | гружена| ка +--------+ Рисунок 9.18. Диаграмма состояний страницы 274 ка" к странице с того момента, как страни- ца была загружена в память. Процесс, обратившийся к странице после второго просмотра страниц "сборщиком", сбросил ее "возраст" в 0. После каждого прос- мотра пользовательский процесс обращался к странице вновь, но в конце концов "сборщик" страниц осуществил три просмотра страницы с момента последнего об- ращения к ней со стороны пользовательского процесса и выгрузил ее из памяти. Если область используется совместно не менее, чем двумя процессами, все они работают с битами упоминания в одном и том же наборе записей таблицы страниц. Таким образом, страницы могут включаться в рабочие множества нес- кольких процессов, но для "сборщика" страниц это не имеет никакого значения. Если страница включена в рабочее множество хотя бы одного из процессов, она остается в памяти; в противном случае она может быть выгружена. Ничего, что одна область, к примеру, имеет в памяти страниц больше, чем имеют другие: "сборщик" страниц не пытается выгрузить равное количество страниц из всех активных областей. Ядро возобновляет работу "сборщика" страниц, когда доступная в системе свободная память имеет размер, не дотягивающий до нижней допустимой отметки, и тогда "сборщик" производит откачку страниц до тех пор, пока объем свобод- ной памяти не превысит верхнюю отметку. При использовании двух отметок коли- чество производимых операций сокращается, ибо если ядро использует только одно пороговое значение, оно будет выгружать достаточное число страниц для освобождения памяти свыше порогового значения, но в результате возвращения ошибочно выгруженных страниц в память размер свободного пространства вскоре вновь опустится ниже этого порога. Объем свободной памяти при этом постоянно бы поддерживался около пороговой отметки. Выгрузка страниц с освобождением памяти в объеме, превышающем верхнюю отметку, откладывает момент, когда объ- ем свободной памяти в сист