При работе с новым оборудованием в Linux довольно часто возникают разнообразные проблемы, прежде всего, конечно, из-за отсутствия драйверов. В принципе, драйвер можно написать самостоятельно, но на этот подвиг решится не много людей. Большинство пользователей вынуждены ждать, когда производитель оборудования сам позаботится об этом. К счастью, в последнее время драйверы для значительного числа новых устройств выпускаются достаточно оперативно.
Но проблемы могут быть связаны и с использованием драйвера. Ярким примером служит установка Linux на машины с винчестерами Serial ATA (SATA). Поставляемые с контроллерами SATA драйверы обычно выполнены в виде загружаемых модулей и не могут быть статически скомпилированы в ядре Linux. Иными словами, при загрузке системы с винчестеров SATA образуется замкнутый круг – для того чтобы воспользоваться винчестером, необходимо сначала загрузить модуль, но сам модуль находится на винчестере.
На самом деле проблема решается достаточно просто – с помощью технологии первоначального диска RAM (вольный перевод термина Initial RAM Disk). В образ диска RAM помещаются необходимые для дальнейшей работы модули, а в стартовом сценарии описывается их загрузка. При старте ядро использует корневую файловую систему, находящуюся на диске RAM, и только после выполнения некоторых действий (как правило, это загрузка модулей) заменяет ее на корневую файловую систему, расположенную на физическом диске. В дальнейшем загрузка продолжается обычным образом и отведенная под диск RAM область памяти освобождается для других задач.
Подобная технология используется во многих дистрибутивах (RedHat, ASPLinux и др.). Все необходимое – а именно программа mkinitrd – поставляется с самим дистрибутивом. Особенных трудностей возникнуть не должно, так как все достаточно подробно описано в документации. В Slackware Linux по умолчанию не применяется initrd, поэтому для ее использования придется выполнить дополнительные действия.
ПОДГОТОВКА ЯДРА С ПОДДЕРЖКОЙ ТЕХНОЛОГИИ INITRD
Прежде чем устанавливать дистрибутив, необходимо подготовить специальную сборку ядра и образ диска RAM. Для выполнения этих операций потребуется машина с уже работающей ОС Linux. В принципе, дистрибутив может быть любой, но желательно использовать сам Slackware. Ниже описывается вся подготовительная процедура с учетом применения Slackware Linux 9.1.
Сборка будет производиться с ядром версии 2.6.0, хотя это условие не является обязательным. В случае ветви 2.4 действия по включению технологии initrd аналогичны описанным ниже, но при сборке ядра необходимые опции будут находиться в другом месте.
Итак, при создании ядра необходимо выбрать поддержку диска RAM. Она активизируется в разделе Device Drivers Б?? Block Devices. Выбор опции производится путем указания звездочки, т. е. статического включения в ядро. Кроме того, следует задать обюем оперативной памяти, выделяемой под диск RAM. Он должен соответствовать размеру, который занимает образ диска. Обратите внимание на то, что файл образа (обычно его имя initrd.img) сжат программой gzip. И, конечно, надо отметить пункт Initial RAM disk (initrd) support (его название говорит само за себя).
Ядро должно поддерживать файловую систему ext2, поскольку именно она используется при создании образа диска RAM. Остальные параметры выбираются по необходимости. После этого ядро и загружаемые модули собираются стандартным образом.
В дальнейшем предварительно собранное ядро и все модули желательно записать на CD-R и при установке вручную заменить стандартное, поставляемое с дистрибутивом ядро на собранное самостоятельно.
ПОДГОТОВКА ОБРАЗА ДИСКА RAM
Сначала нам потребуется создать файл, размер которого равен обюему памяти, выделенной под диск RAM.
dd if=/dev/zero of=initrd.flat.img bs=1024 count=4098
В этом файле создаем файловую систему ext2:
mkfs -t ext2 -m0 initrd.flat.img
Кроме того, необходимо создать точку монтирования ~/initrd, к которой будет подключена находящаяся в файле файловая система. Для подключения файловой системы текущее ядро должно поддерживать устройства loop.
mkdir ~/initrd
mount -t ext2 initrd.flat.img ~/initrd -o loop
В каталоге ~/initrd следует создать структуру каталогов корневой файловой системы и перенести в нее все необходимые при загрузке файлы. Итоговый список довольно обширен:
cd ~/initrd
mkdir -p bin etc lib/modules dev proc usr
ln -s bin sbin
cd /usr
ln -s ../bin bin
cd ..
rm -R lost+found
Каталог rootfs, к которому будет подключаться корневая находящаяся на жестком диске файловая система, лучше создать заранее:
mkdir rootfs
Для запуска сценариев потребуется командный процессор (shell). Места в оперативной памяти под образ диска RAM отводится не так много, поэтому желательно, чтобы он был небольшим, например ash. Если пакет ash не установлен, то его следует установить.
Затем надо узнать, какие библиотеки необходимы для работы ash. Для определения библиотек можно воспользоваться программой ldd:
ldd /bin/ash
Файл ash и необходимые для него библиотеки следует скопировать в каталог, где находятся файлы образа диска RAM:
cd bin
cp /bin/ash ./
На самом деле некоторые нужные нам библиотеки – это символьные ссылки на реальные библиотеки, поэтому их необходимо скопировать и создать указывающие на них символьные ссылки. Тех же самых библиотек будет достаточно для работы и других программ, которые мы будем использовать при загрузке с помощью initrd.
Кроме того, необходимо создать символьную ссылку sh, так как в сценарии запуска обычно включается вызов именно этого интерпретатора:
ln -s ash sh
cd ../lib
cp /lib/libc-2.3.2.so ./
ln -s libc-2.3.2.so libc.so.6
cp /lib/ld-2.3.2.so ./
ln -s ld-2.3.2.so ld-linux.so.2
Для загрузки модулей воспользуемся программой insmod.
cd ../bin
cp /sbin/insmod ./
Разумеется, нам потребуется программа mount, а также файл /etc/fstab. В файле /etc/fstab достаточно описать монтирование только корневого каталога:
cp /bin/mount ./
cp /etc/fstab ~/initrd/etc/
Кроме указанных нужны программы init, chroot и pivot_root:
cp /sbin/init ./
cp /sbin/pivot_root ./
cp /usr/sbin/chroot ./
Теперь необходимо создать файлы тех устройств, которые будут использоваться на момент загрузки:
cd ../dev
mknod console c 5 1
mknod null c 1 3
mknod ram0 b 1 0
mknod ram1 b 1 1
mknod systty c 4 0
mknod tty1 c 4 1
mknod tty2 c 4 2
mknod tty3 c 4 3
mknod tty4 c 4 4
mknod tty5 c 4 5
mknod tty6 c 4 6
В частности, потребуются файлы таких устройств, как дисковые накопители из числа тех, которые будут использоваться при старте системы. Это могут быть файлы с интерфейсом устройств IDE (hdXX) или SCSI (sdXX) – все зависит от того, как диск SATA виден в системе. На самом деле достаточно создать файлы устройства для того винчестера, на котором находится корневая файловая система и файл ее раздела. В нашем примере корневой каталог расположен на диске /dev/hda6:
mknod hda b 3 0
mknod hda6 b 3 6
С параметрами файлов устройств можно ознакомиться в документации к ядру в файле Documentation/ devices.txt.
Необходимые модули копируем в каталог lib/modules. Не забывайте, что иногда для загрузки указанного модуля нужны другие модули, поэтому придется копировать все необходимые модули. Файлы можно располагать в любом месте создаваемой файловой системы, но в соответствии с устоявшейся традицией лучше поместить их в lib/modules.
Теперь самое главное – в корне образа диска RAM создаем исполняемый файл linuxrc, который будет запускаться на выполнение после загрузки ядра. Это файл в формате shell script, где следует выполнить следующие действия:
- загрузка необходимых для работы модулей;
- замена временной корневой файловой системы на реальную, находящуюся на диске;
- запуск процесс init для продолжения нормальной загрузки системы.
Пример файла linuxrc приведен в одноименной врезке. Файл сценария обязательно должен быть исполняемым!
Для отключения файловой системы /initrd – после загрузки она останется подключенной – в начале файла letc/rc.d/rc.S необходимо добавить следующие строки:
if [ -x /initrd/linuxrc ]; then
/bin/umount /initrd
/sbin/blockdev --flushbufs /dev/ram0
fi
Прежде всего следует проверить факт наличия файла linuxrc в каталоге initrd – таким образом мы сможем установить, использовался ли initrd при загрузке системы. Если этот файл существует, тогда диск RAM подключен. Отключив его, при помощи программы blockdev освобождаем память, занимаемую диском RAM.
Итак, мы перенесли и создали все необходимые файлы образа диска RAM. Выйдя из каталога, демонтируем его и обязательно сжимаем при помощи gzip:
cd
umount ~/initrd
gzip -9c initrd.flat.img > initrd.img
Файл образа диска RAM готов.
УСТАНОВКА SLAСKWARE LINUX
Устанавливаемый дистрибутив будет использовать ядро версии 2.6.0 (не входящее в стандартную поставку), поэтому необходимо создать дополнительный диск и разместить на нем заранее собранные ядро, загружаемые модули и полностью подготовленный образ диска RAM.
Как и при обычной установке Slackware Linux, загрузка производится с первого (установочного) CD-ROM. Но перед разбиением жестких дисков на разделы все, поставляемые для контроллера SATA, модули загружаем вручную (их следует заранее разместить на дополнительном диске). Дальнейшая процедура установки проходит по стандартному сценарию, но конфигурацию загрузчика LILO необходимо пропустить – его придется настраивать вручную позже.
После установки дистрибутива машину перегружать не нужно, она все равно не загрузится. Дополнительный диск с ядром, модулями и образом диска RAM надо подключить, например, к каталогу /cdrom. Кроме того, следует подключить тот раздел винчестера, где будет находиться корневой каталог, например к каталогу /mnt.
В каталог /mnt/boot следует скопировать файл ядра и образ диска RAM с CD-ROM, а модули ядра – в каталог /mnt/lib/modules/2.6.0 (название последнего должно соответствовать номеру ядра, указанного в файле Makefile, находящемся в корне исходных кодов ядра).
Конфигурационный файл загрузчика LILO создадим в каталоге /mnt/etc. Предположим, что файл ядра называется vmlinuz-initrd, а образ диска RAM – initrd.img. Тогда файл lilo.conf будет выглядеть следующим образом:
boot=/dev/hda
prompt
timeout=50
restricted
password=12345
image=/boot/vmlinuz-initrd
root=/dev/ram0
label=initrd
initrd=/boot/initrd.img
vga=normal
append=«init=/linuxrc rw»
Обязательно следует указать, что корневая файловая система будет расположена в
/dev/ram0.
Позже, в сценарии linuxrc, при помощи программы pivot_root мы подставим реальную корневую файловую систему.
Параметр initrd определяет, где находится файл с образом диска RAM, а в append устанавливаются дополнительные опции, которые будут переданы ядру при загрузке: вместо стандартного процесса init будет запускаться сценарий linuxrc, корневая файловая система станет монтироваться в режиме полного доступа.
Сохранив файл, программу lilo запустите следующим образом:
chroot /mnt lilo
Кроме того, нам потребуется создать каталог initrd, который будет использоваться в процессе загрузки:
mkdir /mnt/initrd
После этого машину можно перегрузить.
НЕ ТОЛЬКО ЗАГРУЗКА МОДУЛЕЙ
Технология initrd – очень мощный инструмент, позволяющий более гибко настраивать процесс загрузки системы. Ее можно применять не только для загрузки модулей контроллеров, но и для запуска системы с программных массивов RAID или предварительного запуска LVM.
Хочется надеяться, что наши советы помогут разобраться с основами применения технологии initrd. В качестве интересного примера предлагаем ознакомиться с исходными кодами сценария mkinitrd. Пакет mkinitrd не поставляется со Slackware Linux, но его можно найти, например, в дистрибутиве ASPLinux по адресу: ftp.asplinux.ru. Полезно также изучить документацию, поставляемую с исходными кодами ядра, – файл Documentation/initrd.txt.
Артур Крюков – преподаватель центра компьютерного обучения «Специалист» при МГТУ им. Н. Э. Баумана. С ним можно связаться по адресу: akrjukov@specialist.ru.
Пример файла linuxrc
#! /bin/sh
###### Загрузка модулей #####
echo «Loading modules ...»
# При помощи программы insmod следует загрузить
# все необходимые модули. К файлу модуля
# следует указать полный путь.
# SATA_MODULE – это условное название, в действительности
# надо указать файл реального модуля.
/bin/insmod /lib/modules/SATA_MODULE
###### Монтирование корневой файловой системы #####
# Тип и опции монтирования файловой системы
# должны соответствовать реальной ситуации
echo «Mountig rootfs ...»
/bin/mount -t ext3 /dev/hda6 rootfs -o ro
###### Замещение корневой файловой системы #####
# Программа pivot_root предназначена для замещения
# текущей корневой файловой системы на новую.
# В нашем примере мы сначала переходим в каталог,
# где находится корневая файловая система на жестком диске,
# а затем вызываем программу pivot_root, где в качестве
# параметров указывается текущий каталог и каталог,
# куда будет подключена старая корневая файловая
# система. Таким образом, после вызова программы файлы,
# находящиеся на диске RAM, будут видны в каталоге initrd.
echo «Replace rootfs ...»
cd rootfs
/bin/pivot_root . initrd
###### Запуск стандартной системы инициализации #####
# Для продолжения выполнения нормальной
# загрузки системы запускаем init.
# chroot необходимо выполнить обязательно.
# Обратите внимание на путь к устройству console.
# В пути не надо указывать корень.
echo «Start init ...»
exec /usr/bin/chroot . /sbin/init < dev/console > dev/console 2>&1
# конец сценария.