Внутреннее устройство Slax
Структура каталогов Slax
Все файлы данных Slax находятся на загрузочном носителе в одном каталоге. Вполне естественно, что имя этого каталога «slax». Вся магия происходит внутри. На схеме ниже показана упрощенная структуры каталогов; приведены только интересующие нас файлы:
slax
├─── boot
│ ├─── isolinux.bin
│ ├─── syslinux.cfg
│ ├─── initrfs.img
│ ├─── vmlinuz
│ └─── ...
├─── changes
├─── rootcopy
├─── 01-core.sb
├─── 02-xorg.sb
├─── 03-desktop.sb
├─── 04-chromium.sb
└─── …
Загрузка ядра Linux
Когда BIOS вашего компьютера загружает Slax, он фактически запускает загрузчик SYSLINUX. Сам загрузчик хранится в файле isolinux.bin или ldlinux.sys, в зависимости от вашего загрузочного носителя - CD/DVD использует isolinux.bin, USB-диск или жесткий диск - ldlinux.sys.
Дальнейшие действия загрузчика SYSLINUX зависят от содержимого файла конфигурации syslinux.cfg. В Slax в этом файле содержатся инструкции вывода на экран логотипа и (по требованию) меню загрузки - если пользователь нажимает клавишу до истечения времени ожидания. Когда обратный отсчет заканчивается (или пользователь выбирает пункт меню), SYSLINUX загружает в память два файла: vmlinuz (ядро Linux) и initrfs.img (базовая корневая файловая система). Прогресс отображается непрерывным потоком точек на экране. Как только эти файлы загружены, управление передается исполняемому файлу vmlinuz для запуска ядра Linux.
Инициализация
В обычных условиях (когда стандартный дистрибутив Linux запускается с жесткого диска), ядро Linux монтирует корневую файловую систему с жесткого диска, и в качестве основного процесса выполняется /sbin/init, который заботится о запуске системы. В Slax ситуация иная - нет жесткого диска, с которого корневая файловая система могла бы быть смонтирована, но ядру, безусловно, нужно запустить процесс инициализации. Для этого Slax содержит базовую файловую систему в файле initrfs.img - это сжатый архив CPIO с некоторыми каталогами и файлами внутри, включая основные инструменты Linux (команды) и требуемый init.
Поэтому после того, как ядро успешно запущено и полностью контролирует ваш компьютер, последняя задача, которую оно выполняет - найти упомянутый архив CPIO в памяти (как вы помните, он был загружен из файла initrfs.img загрузчиком syslinux), распаковать его в область памяти, которая действует как временная корневая файловая система, называемая initramfs, и выполнить оттуда процесс инициализации /init.
Промежуточная инициализация
На данный момент у нас работает полностью инициализированное ядро Linux, область initramfs в памяти заполнена временной корневой файловой системой, содержащей только самые основные команды Linux, и промежуточная инициализация только начинается.
Наличие временной корневой файловой системы в initramfs не является идеальным, поскольку она не поддерживает системный вызов pivot_root - важная операция, которая будет использоваться позже в процессе загрузки. Нам нужно переключиться с вспомогательной initramfs на полоценную корневую файловую систему. Для этого временный init сначала монтирует файловую систему tmpfs в директорию /m, перемещает туда все файлы и каталоги, включая сам скрипт init, и использует switch_root, чтобы сделать этот tmpfs/m новым корнем и перезапустить сам init там. Звездочкой обозначен каталог, который перемещается.
initramfs от имени пользователя root:
(initramfs)
/
├─── bin
│ ├─── sh
│ ├─── mount
│ └─── ...
├─── dev
├─── mnt
├─── m (tmpfs) ★
├─── memory
├─── proc
├─── sys
├─── init
└─── shutdown
initramfs после перехода в tmpfs:
(initramfs)
/
└─── m (tmpfs) ★
├─── bin
│ ├───sh
│ ├───mount
│ └─── ...
├─── dev
├─── mnt
├─── memory
├─── proc
├─── sys
├─── init
└─── shutdown
tmpfs после switch_root:
(tmpfs) ★
/
├─── bin
│ ├─── sh
│ ├─── mount
│ └─── ...
├─── dev
├─── mnt
├─── memory
├─── proc
├─── sys
├─── init
└─── shutdown
Как бы странно ни выглядело это действие в целом (у нас получилась та же структура каталогов, что и раньше, похоже, существенных изменений нет), на самом деле изменение значительное. С этого момента временная корневая файловая система находится на tmpfs вместо initramfs, и, таким образом, операция pivot_root будет доступна при необходимости в будущем.
Вы можете задаться вопросом, почему текущая корневая файловая система до сих пор помечена как временная. Это потому, что мы все еще находимся в самом начале этапа построения, и мы просто создадим полоценную рабочую корневую файловую систему позже, как будет объяснено ниже, путем объединения сжатых образов данных Slax в AUFS.
Поиск данных Slax
Прежде чем процесс init сможет начать поиск данных Slax на доступных устройствах, необходимо настроить рабочую среду. Файловые системы proc и sysfs монтируются в каталоги /proc и /sys соответственно. Некоторые важные драйверы ядра, такие как aufs, squashfs и loop, загружаются с помощью modprobe, а файлы устройств создаются в каталоге /dev командой mdev.
Как только устройства хранения становятся доступны через файлы устройств в /dev, в ход идет команда blkid для определения тех, которые могут быть смонтированы (которые содержат файловую систему, известную работающему ядру). Устройства проверяются (монтируются только для чтения в /memory/data/) один за другим, пока не будет найден рабочий каталог с данными Slax. Затем обрабатываются все файлы с расширением .sb (Slax Bundles - пакеты или модули Slax) - для каждого модуля создается каталог в /memory/bundles/, и они (по сути - сжатые файлы образов squashfs) монтируются в него. На приведенной ниже диаграмме содержимое squashfs выделено жирным курсивом.
(tmpfs)
/
├─── bin
├─── dev
├─── ...
├─── memory
│ ├─── bundles
│ │ ├─── 01-core.sb ................ < ───┐
│ │ │ ├─── bin │
│ │ │ ├─── etc │
│ │ │ ├─── sbin │
│ │ │ └─── ... │
│ │ ├─── 02-xorg.sb ......................│...
│ │ │ ├─── etc │ :
│ │ │ ├─── usr │ :
│ │ │ └─── ... │ :
│ │ ├─── 03-desktop.sb ...................│..:...
│ │ │ ├─── usr │ : :
│ │ │ └─── ... │ : :
│ │ └─── ... │ : : точки
│ ├─── data (точка монтирования диска slax) │ : : монтирования
│ │ └─── slax │ : : squashfs
│ │ ├─── boot │ : :
│ │ ├─── changes │ : :
│ │ ├─── rootcopy │ : :
│ │ ├─── 01-core.sb ──── > ──── > ───┘ : :
│ │ ├─── 02-xorg.sb ....................: :
│ │ ├─── 03-desktop.sb ....................:
│ │ └─── ...
│ ├─── changes (пока пустой)
│ └─── union (пока пустой)
├─── proc (точка монтирования procfs)
├─── sys (точка монтирования sysfs)
└─── init
Объединение в AUFS
Различные части конечной корневой файловой системы теперь смонтированы только для чтения в отдельных папках в /memory/bundles. Основные системные утилиты и библиотеки Linux, такие как /bin/bash или /lib/ld-linux.so, находятся в /memory/bundles/01-core.sb/, файлы, относящиеся к среде рабочего стола, можно найти в /memory/bundles/03-desktop.sb/ и так далее. Объединение их в общую корневую файловую систему, которая будет доступна также и для записи, возможно только благодаря AUFS - объединяющей файловой системе, разработанной Junjiro Okajima. AUFS может принимать несколько папок (так называемые ветви) и объединять их в один каталог. Это именно то, что происходит дальше: разделенные части сливаются вместе с каталогом /memory/changes/ в объединенную файловую систему AUFS, которая монтируется в /memory/union.
(tmpfs)
/
├─── ...
└─── memory
├─── bundles
│ ├─── 01-core.sb ───────── > ──────┐
│ ├─── 02-xorg.sb ..................│.......
│ ├─── 03-desktop.sb ...............│......:........
│ └─── ... │ : :
├─── changes ──────── > ───────┐ │ : :
├─── ... ˅ ˅ : :
└─── union < ═══════ < ═══════ < ───── < ─────┘ < ────┘
├─── bin
├─── etc собранная AUFS
├─── mnt
├─── root
├─── sbin
├─── usr
├─── ...
└─── var
Изменения
Каталог /memory/changes доступен для записи, поэтому все, что смонтировано AUFS в /memory/union также доступно для записи. Все новые или измененные файлы внутри AUFS помещаются в этот каталог после того, как система создаст или изменит их. Поскольку каталог для изменений находится в tmpfs (то есть в оперативной памяти), все новые и измененные файлы хранятся в оперативной памяти и, таким образом, теряются при перезагрузке.
Тем не менее, если Slax запускается с записываемого носителя, такого как USB-устройство или жесткий диск, он распознает это и монтирует перезаписываемый диск в /memory/changes/ до того, как он будет объединен с другими ветвями в AUFS, что фактически означает, что измененные и новые файлы будут храниться на загрузочном устройстве, а не в оперативной памяти, и перезагрузка не сотрет их. Эта функция называется "сохранением изменений" и может быть включена или выключена с помощью параметра меню загрузки.
Переключение с временной на рабочую файловую систему
На данный момент полностью записываемая конечная корневая файловая система была создана в /memory/union. Жизнь временного инициализирующего процесса подходит к концу. Он использует системные вызовы pivot_root и chroot для создания из /memory/union нового корня, перемещая временный корень tmpfs в /run/initramfs/ в новом корне. Звездочки на диаграммах ниже показывают, что и куда движется. Наконец, выполняется настоящий /sbin/init из корневой файловой системы AUFS и начинается загрузка операционной системы Slax.
Корень tmpfs перед системным вызовом pivot_root:
(tmpfs) ★
/
├─── ...
└─── memory
└─── union (aufs) ★★
├─── bin
├─── etc
├─── root
├─── run
│ └─── initramfs (пустой)
├─── sbin
│ ├─── ...
│ └───init
├─── usr
├─── ...
└─── var
aufs как новый корень файловой системы:
(aufs) ★★
/
├─── bin
├─── etc
├─── root
├─── run
│ └─── initramfs (tmpfs) ★
│ ├─── ...
│ └─── memory
│ └─── union (пустой)
├─── sbin
│ ├─── ...
│ └─── init <- выполняется
├─── usr
├─── ...
└─── var
Добавление модулей в Slax на лету
Корневая файловая система доступна для записи, и мы можем установить новые программные пакеты обычным способом, распаковав их. Но есть еще возможность добавить новые файлы и каталоги в Slax на лету без установки каких-либо пакетов. Благодаря тому, что Slax работает с AUFS в качестве пользователя root, мы можем взять некоторую другую сжатую файловую систему squashfs, смонтировать ее в каталог, который находится за пределами дерева AUFS (например, в каталог /run/initramfs/memory/bundles/name.sb/, который находится на tmpfs), а затем выполнить команду remount, которая добавляет вновь смонтированный каталог в AUFS как новую ветвь.
Все файлы и каталоги из нового модуля squashfs мгновенно появятся в файловой системе, как если бы они были там с самого начала, в то время как распаковка затребованных файлов выполняется на лету и только для тех, к которым фактически осуществляется доступ.
Точно так же мы можем удалить ранее добавленную ветку AUFS (смонтированные squashfs) из корня aufs другой командой remount. Файлы, которые были частью ветки, моментально исчезнут из системы, что фактически удаляет пакет.
Завершение работы Slax
Когда Slax завершает работу - для выключения системы или для перезагрузки, - он выполняет все стандартные задачи, как и любой другой Linux, например, размонтирует все разделы, смонтированные пользователем, завершает все процессы и так далее. Но поскольку загрузочное устройство все еще может быть смонтировано и использовано для сохранения изменений в самом конце, необходимо выполнить еще некоторые шаги до того, как произойдет реальное отключение питания, чтобы убедиться, что загрузочное устройство размонтировано безопасно.
В тот момент, когда init считает, что можно выключить систему, вместо этого Slax переключается обратно на initramfs (это автоматически обрабатывается systemd) и выполняет скрипт завершения работы /run/initramfs/shutdown. Это сценарий, который заботится о размонтировании оставшегося смонтированного диска, с которого запустился Slax, чтобы загрузочное устройство было безопасно извлечено. В конце компьютер перезагружается или выключается в зависимости от того, что пользователь намеревался сделать.