
Действия ядра Linux в процессе начальной загрузки
Итак, досистемная загрузка проходит в три этапа.
Загрузчик из ПЗУ определяет, с каких устройств можно грузиться и, возможно, предлагает пользователю выбрать одно из них. Он загружает с выбранного устройства первичный загрузчик и передает ему управление. Первичный загрузчик определяет (а чаще всего - знает), где находится вторичный загрузчик - большая и довольно интеллектуальная программа. Ему это сделать проще, чем программе из ПЗУ: во-первых, потому что для каждого устройства первичный загрузчик свой, а во-вторых, потому что его можно легко изменять при изменении настроек загружаемой системы. В схеме, предлагаемой LILO и GRUB, первичный загрузчик не вступает в разговоры с пользователем, а немедленно загружает вторичный и передает ему управление. Вторичный загрузчик достаточно умен, чтобы знать, где находится ядро системы (возможно, не одно), предложить пользователю несколько вариантов загрузки на выбор, и даже, в случае GRUB, разрешает задавать собственные варианты загрузки. Его задача - загрузить в память ядро и все необходимое для старта системы (иногда - модули, иногда - стартовый виртуальный диск ), настроить все это и передать управление ядру. Ядро - это и мозг, и сердце Linux. Все действия, которые нельзя доверить отдельной подзадаче (процессу) системы, выполняются ядром. Доступом к оперативной памяти, сети, дисковым и прочим внешним устройствам заведует ядро. Ядро запускает и регистрирует процессы, управляет разделением времени между ними. Ядро реализует разграничение прав и вообще определяет политику безопасности, обойти которую, не обращаясь к нему, нельзя просто потому, что в Linux больше никто не предоставляет подобных услуг.
Ядро работает в специальном режиме, так называемом «режиме супервизора», позволяющем ему иметь доступ сразу ко всей оперативной памяти и аппаратной таблице задач. Процессы запускаются в «режиме пользователя»: каждый жестко привязан ядром к одной записи таблицы задач, в которой, в числе прочих данных, указано, к какой именно части оперативной памяти этот процесс имеет доступ. Ядро постоянно находится в памяти, выполняя системные вызовы - запросы от процессов на выполнение этих подпрограмм.
Ядро. Набор подпрограмм, используемых для организации доступа к ресурсам компьютера, для обеспечения запуска и взаимодействия процессов, для проведения политики безопасности системы и для других действий, которые могут выполняться только в режиме полного доступа (т.н. «режиме супервизора»).
Функции ядра после того, как ему передано управление, и до того, как оно начнет работать в штатном режиме, выполняя системные вызовы, сводятся к следующему.
Сначала ядро определяет аппаратное окружение. Одно и то же ядро может быть успешно загружено и работать на разных компьютерах одинаковой архитектуры, но с разным набором внешних устройств. Задача ядра - определить список внешних устройств, составляющих компьютер, на котором оно оказалось, классифицировать их (определить диски, терминалы, сетевые устройства и т.п.) и, если надо, настроить. При этом на системную консоль (обычно первая виртуальная консоль Linux) выводятся диагностические сообщения (впоследствии их можно просмотреть утилитой dmesg
).
Затем ядро запускает несколько процессов ядра. Процесс ядра - это часть ядра Linux, зарегистрированная в таблице процессов. Такому процессу можно послать сигнал и вообще пользоваться средствами межпроцессного взаимодействия, на него распространяется политика планировщика задач, однако никакой задаче в режиме пользователя он не соответствует - это просто еще одна ипостась ядра . Команда ps -ef
показывает процессы ядра в квадратных скобках, кроме того, в Linux принято (но не обязательно), чтобы имена таких процессов начинались на k
: [kswapd]
, [keventd]
и т.п.
Далее ядро подключает (монтирует) корневую файловую систему в соответствии с переданными параметрами (в наших примерах - root=/dev/hda5
). Подключение это происходит в режиме «только для чтения» (read-only): если целостность файловой системы нарушена, данный режим позволит, не усугубляя положения, прочитать и запустить утилиту fsck
(file system check). Позже, в процессе загрузки, корневая файловая система подключится на запись.
Наконец, ядро запускает из файла /sbin/init
первый настоящий процесс. Идентификатор процесса (PID) у него равен единице, он - первый в таблице процессов, даже несмотря на то, что до него там были зарегистрированы процессы ядра. Процесс init
- очень старое изобретение, он чуть ли не старше самой истории UNIX, и с давних пор его идентификатор равен 1.