Перевод статьи “Введение в initramfs, новую модель начальных RAM-дисков”
Источник: Introducing initramfs, a new model for initial RAM disks на сайте Linuxdevices.com
Предисловие: Эта статья рассказывает об initramfs, возможности Linux 2.6, которая, в отличии от ramdisk’а, как в случае с файловой системой initrd, позволяет размещать начальную корневую файловую систему и программу инициализации в кеше памяти ядра,. Автор утверждает, что по сравнению с initrd initramfs может увеличить гибкость во время загрузки и эффективность использования памяти.
Интересная особенность может пригодиться разработчикам встраиваемых решений на основе linux, так как позволяет относительно просто использовать initramfs в качестве основной файловой системы.
Описание проблемы (или почему “root=” уже не приемлем)
Когда ядро linux загружает систему, оно должно найти и запустить первую пользовательскую программу, обычно называемую “init”. Пользовательская программа находится в файловой системе, поэтому ядро должно найти и примонтировать первую (т.н. “корневую”) файловую систему в случае успешной загрузки.
Как правило, доступные файловые системы перечислены в файле /etc/fstab, где их может найти программа монтирования. Но /etc/fstab в свою очередь тоже является файлом, хранимым в файловой системе. Нахождение самой первой файловой системы - это проблема курицы и яйца, и чтобы решить ее, разработчики ядра создали параметр командной строки “root=”, чтобы указать, на каком устройстве расположена корневая файловая система.
Пятнадцать лет назад выражение “root=” было легко понять. Это было время дискет и небольшого числа разделов на жестких дисках. В наши дни корневая файловая система могла быть размешена на десятке разных типов оборудования (SCSI, SATA, flash MTD), или даже быть распределена на нескольких из них, объединенных в RAID-массив. Это расположение может меняться от одной загрузки к другой, так как USB устройства могут быть подключены к системе с несколькими USB портами - следовательно, будет несколько USB устройств, и как определить какое из них нужное? Корневая файловая система может быть сжата (как?), зашифрована (с каким ключем?), или примонтирована через петлевой интерфейс (куда?). Она может даже располагаться где-то на удаленном сервере, что потребует от ядра получения динамического IP-адреса, выполнения поиска по DNS, и подключения к удаленному серверу (с указанием имени пользователя и пароля) - и все это должно происходить до того, как ядро сможет найти и запустить первую пользовательскую программу.
Сейчас выражение “root=” просто не дает достаточной информации. Даже если предусматривать множество случаев поведения в ядре, это никак не может помочь при нумерации устройств, ключей шифрования или удаленного входа по сети, которые могут сильно варьироваться от системы к системе. Хуже всего то, что программирование ядра на выполнение этих видов сложных задач подобно написанию веб-приложения на ассемблере: это может быть выполнено, но гораздо проще использовать специальные средства для совершения этих действий. А ядро проектируется для того, чтобы выполнять свои собственные задачи.
Нахождение решения
Ядра Linux 2.6 поддерживают компактную начальную корневую файловую систему, размещающуюся непосредственно в памяти ядра. Эта файловая система содержит программу с именем “/init”, которую ядро запускает в качестве своей первой программы. И начиная с этого момента поиск других файловых систем, содержащих некоторые другие программы, которые нужно запустить - уже проблема не ядра, а работа для этой программы “/init”.
Содержимое initramfs - не главное. Если настоящая корневая файловая система находится на зашифрованном блочном сетевом устройстве, и сетевой адрес, логин, и ключ расшифровки находятся на USB юстройстве, называемом “Larry” (который требует пароль для доступа), то initramfs системы может содержать специализированную программу, которая знает все об этом, и замечательно выполняет требуемые действия.
Для систем, которым не требуются большие корневые файловые системы, вообще не нужно размещать или переключаться на какую-либо другую файловую систему.
В чем отличия от initrd?
Ядро linux уже имеет способ предоставить корневую файловую систему, размещаемую в памяти - механизм initrd. Для ядер 2.4 и более ранних initrd - единственный способ для выполнения этого рода действий. Но разработчики ядра включили новый механизм в ядро 2.6 по нескольким причинам.
ramdisk vs ramfs
Ramdisk (подобно initrd) - это блочное устройство, размещенное в оперативной памяти, которое подразумевает, что есть часть памяти фиксированной величины, которая может быть отформатирована и подготовлена при помощи специальных утилит (таких как mke2fs и losetup) и подобно всем блочным устройствам требует драйвер файловой системы для интерпретации данных при запуске. Также существует искусственное ограничение по размеру на пустое пространство (если ramdisk не полон, дополнительная память, которую он занимает, не может быть использована для других целей) и ограничение на размер (если ramdisk’у не хватает памяти, а другая память свободна, вы никак не можете увеличить размер памяти, доступный для ramdisk без его переформатирования)
Но ramdisk’и в действительности занимают еще больше места из-за кеширования. Linux спроектирован таким образом, чтобы кешировать все файлы и директории, прочитанные с блочных устройств или записанные на них. Таким образом, Linux копирует данные, получаемые с ramdisk’а или записываемые на него в “кеш страниц” (для данных файлов) и в “кеш директорий” (для заголовков директорий) Обратной стороной маскировки ramdisk’а под блочное устройство является необходимость обращаться с ним как с блочным устройством.
Несколько лет назад Линусу Торвальдсу пришла в голову замечательная мысль: почему бы не монтировать кеш Linux подобно файловой системе? Просто держать файлы в кеше и никогда не избавляться от них пока они не будут удалены или пока система не будет перезагружена? Линус написал небольшую обертку к кешу, названную “ramfs”, а другие разработчики ядра создали усовершенствованную ее версию, названную “tmpfs” (которая может записывать данные в пространство подкачки, и ограничивать размер, отдаваемый точке монтирования, так что она может заполняться перед потреблением всей доступной памяти). Initramfs - это один из примеров tmpfs.
Размещенные в оперативной памяти файловые системы автоматически уменьшаются или увеличиваются для того, чтобы разместить весь объем данных, которые они содержат. Добавление новых файлов в ramfs (или увеличение размера существующих файлов) автоматически приводит к выделению большего количества памяти, а удаление или уменьшение размера файлов освобождает эту память. Здесь нет дублирования между блочным устройством и кешем, так как это не блочное устройство. Копия в кеше - это всего лишь только копия данных. Лучше всего то, что это не новая система, а просто новое применение для существующей системы кеширования Linux, в которой практически ничего не изменено, это очень простое, и базирующееся на тщательно протестированной инфраструктуре решение.
Системе, использующей initramfs в качестве корневой файловой системы, необязательна даже поддержка отдельного драйвера файловой системы в ядре, потому что нет блочных устройств, которые нужно интерпретировать в качестве файловых системм. Файлы просто находятся в памяти.
initrd vs initramfs
Изменения в нижележащей инфраструктуре стали причиной для разработчиков ядра создать новую реализацию, но сначала они произвели чистку от массы неправильных поведений и ошибочных связей.
Initrd был спроектирован в качестве интерфейса к старому коду обнаружения корневого устройства “root=”, но не в качестве замены для него. Он запускал программу, называемую “/linuxrc”, которая была адаптирована к выполнению установочных функций (подобных авторизации по сети, определению того, какой из нескольких устройств содержит корневой раздел, или связыванию устройства петлевого интерфейса с файлом), эта программа сообщала ядру, какое блочное устройство содержит настоящее корневое устройство (путем записи de_t в /proc/sys/kernel/real-root-dev), а затем возвращала ядру управление, так что ядро могло смонтировать настоящее корневое устройство и выполнить настоящую программу init.
Предполагалось, что настоящее корневое устройство является блочным устройством, отличным от сетевого, а также, что initrd сам не переходит к настоящей корневой файловой системе. Ядро даже не выполняет “/linuxrc” в качестве специального процесса с ID 1, поскольку ID процесса (и его особенности, например, невозможность завершить его с помощью “kill -9″) были зарезервированы для init, который ядро ожидает запустить после монтирования реальной корневой файловой системы.
С приходом initramfs разработчики ядра удалили все эти ограничения. Однажды запустив “/init” из initramfs, ядро выполняет требуемые операции и может вернуться к следующим задачам. С initramfs ядро не заботится, где находится настоящая корневая файловая система (потому что пока ей является initramfs), и программа “/init” из initramfs запускается как настоящий init c ID процесса 1. (если init, запущенный из initramfs, нуждается в указании специального идентификатора процесса другой программе, он может сделать это, используя системный вызов exec() подобно тому как это делается обычно )
Подводя итоги
Традиционный параметр командной строки ядра root= до сих пор поддерживается и может использоваться, но новые разработки в области загрузочных RAM-дисков, поддерживаемых ядром, предоставляют куда большие возможности и гибкость для будущих ядер Linux. Следующая статья в этой серии расскажет о том, как вы можете осуществить переход к новому механизму начальных RAM-дисков initramfs.

(4 out of 5)











0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment