Режим ядра и пользовательский режим
Современные вычислительные архитектуры обычно позволяют центральному процессору работать как минимум в двух различных режимах: пользовательском и режиме ядра (который иногда называют защищенным). Аппаратные инструкции позволяют переключаться из одного режима в другой. Соответственно области виртуальной памяти могут быть помечены в качестве части пользовательского пространства или пространства ядра. При работе в пользовательском режиме ЦП может получать доступ только к той памяти, которая помечена в качестве памяти пользовательского пространства. Попытки обращения к памяти в пространстве ядра приводят к выдаче аппаратного исключения. При работе в режиме ядра центральный процессор может получать доступ как к пользовательскому пространству памяти, так и к пространству ядра.
Некоторые операции могут быть выполнены только при работе процессора в режиме ядра. Сюда можно отнести выполнение инструкции halt для остановки системы, обращение к оборудованию, занимающемуся управлением памятью, и инициирование операций ввода-вывода на устройствах. Используя эту конструктивную особенность оборудования для размещения операционной системы в пространстве ядра, разработчики ОС могут обеспечить невозможность доступа пользовательских процессов к инструкциям и структурам данных ядра или выполнения операций, которые могут отрицательно повлиять на работу системы.
Сравнение взглядов на систему со стороны процессов и со стороны ядра
Решая множество повседневных программных задач, мы привыкли думать о программировании, ориентируясь на процессы. Но, прежде чем рассматривать различные темы, освещаемые далее в этой книге, может быть полезно переориентировать свои взгляды на систему, став на сторону ядра. Чтобы контраст стал заметнее, рассмотрим, как все выглядит, сначала с точки зрения процесса, а затем с точки зрения ядра.
В работающей системе обычно выполняется множество процессов. Для процесса многое происходит асинхронно. Выполняемый процесс не знает, когда он будет приостановлен в следующий раз, для каких других процессов будет спланированно время центрального процессора (и в каком порядке) или когда в следующий раз это время будет спланировано для него. Передача сигналов и возникновение событий обмена данными между процессами осуществляются через ядро и могут произойти в любое время. Многое происходит незаметно для процесса. Он не знает, где находится в памяти, размещается ли конкретная часть его пространства памяти в самой оперативной памяти или же в области подкачки (в выделенной области дискового пространства, используемой для дополнения оперативной памяти компьютера). Точно так же процесс не знает, где на дисковом накопителе хранятся файлы, к которым он обращается, — он просто ссылается на файлы по имени. Процесс работает изолированно, он не может напрямую обмениваться данными с другим процессом. Он не может сам создать новый процесс или даже завершить свое собственное существование. И наконец, процесс не может напрямую обмениваться данными с устройствами ввода-вывода, подключенными к компьютеру.
С другой стороны, у работающей системы имеется всего одно ядро, которое обо всем знает и всем управляет. Ядро содействует выполнению всех процессов в системе. Оно решает, какой из процессов следующим получит доступ к центральному процессору, когда это произойдет и сколько продлится. Ядро обслуживает структуры данных, содержащие информацию обо всех запущенных процессах, и обновляет их по мере создания процессов, изменения их состояния и прекращения их выполнения. Ядро обслуживает все низкоуровневые структуры данных, позволяющие преобразовывать имена файлов, используемые программами, в физические местоположения файлов на диске. Ядро также обслуживает структуры данных, которые отображают виртуальную память каждого процесса в физическую память компьютера и в область (области) подкачки на диске. Весь обмен данными между процессами осуществляется через механизмы, предоставляемые ядром. Отвечая на запросы процессов, ядро создает новые процессы и прекращает работу существующих. И наконец, ядро (в частности, драйверы устройств) выполняет весь непосредственный обмен данными с устройствами ввода-вывода, осуществляя по требованию перемещение информации в пользовательские процессы и из них в устройства.
Далее в книге будут встречаться фразы вроде «процесс может создавать другой процесс», «процесс может создать конвейер», «процесс может записывать данные в файл» и «процесс может останавливать свою работу путем вызова функции exit()». Но вам следует запомнить, что посредником во всех этих действиях является ядро, а такие утверждения — всего лишь сокращения фраз типа «процесс может запросить у ядра создание другого процесса» и т. д.