Сегменты, страницы и системные вызовы
32-битное адресное пространство процессора VAX разбито на четыре части, каждая объемом по гигабайту. Первый гигабайт адресов предназначен для кода и данных пользовательской программы, второй – для пользовательского стека, третий – для системы, четвертый не используется (рис. 5.7).
Каждая из частей имеет собственный указатель на таблицу дескрипторов страниц. Важно отметить, что деление адресного пространства на таблицы не обязательно связано с правами доступа на отдельные страницы – в системной таблице могут быть страницы, доступные для записи из пользовательского режима (на практике этого никогда не бывает, но на уровне диспетчера памяти контроля за этим не реализовано), а в пользовательской – страницы, доступные только ядру.
Рис. 5.7. Адресное пространство VAX
Системная таблица страниц одна во всей системе и содержится в адресных пространствах всех задач. Напротив, пользовательские таблицы у каждой задачи свои (внимательный читатель может отметить определенную параллель между этой структурой и описанным в разд. "Банки памяти" переключателем банков памяти, который присутствует во всех банках). Для того чтобы упростить системе управление пользовательскими таблицами дескрипторов, эти таблицы хранятся не в физическом, а в виртуальном системном адресном пространстве, и при доступе к ним происходит двойная трансляция адреса.
Ядро системы, таким образом, присутствует в адресных пространствах всех задач. Многие системные модули (например, функция для получения текущего реального времени) доступны для чтения из пользовательского режима и могут вызываться непосредственно, как обычные процедуры. Адреса точек входа этих процедур размещены в специальной таблице в начале системного адресного пространства (рис. 5.8).
Другие системные модули (например, подсистема работы с файлами, RMS – Record Management Service (Служба управления записями)) требуют повышения уровня доступа: действительно, если одна из задач работает с файлами с ограниченным доступом, было бы неразумно позволять всем остальным задачам видеть используемые при этом системные буферы. Точки входа этих процедур размещаются в той же таблице, что и прямо вызываемые системные подпрограммы, но тела этих процедур состоят только из двух команд: переключения режима процессора и возврата.
Рис. 5.8. Точки входа системных подпрограмм VAX/VMS
Процедура, работающая в "повышенном" (более привилегированном) режиме процессора, имеет полный доступ ко всем данным режимов с более низким уровнем доступа. Благодаря этому мы можем передать привилегированной процедуре указатель, и она доберется до наших данных простым разрешением этого указателя, без каких бы то ни было специальных команд.
Впрочем, при таком подходе возникает определенная проблема. Поскольку система и пользователь находятся в одном адресном пространстве, пользователь может "подсунуть" системе указатель на страницу, к которой сам не имеет доступа – например, попросить считать нечто из файла в системный сегмент данных. Для исключения таких ситуаций VAX предоставляет команды PROBSR и PROBEW, которые проверяют, существует ли доступ к указанной странице в предыдущем режиме работы процессора. Как мы помним, предыдущий режим сохраняется не только в стеке, но и в слове состояния процесса, и нужно это именно для таких проверок.
Видно, что обойтись без специальных команд все-таки не удалось. К тому же платой за принятое в VAX техническое решение оказалось сокращение полезного адресного пространства задачи в два, а на самом деле даже в четыре (кому нужен стек размером 1 Гбайт?) раза. В 70-е годы, когда разрабатывался VAX, это еще не казалось проблемой.