Daniel Robbins (drobbins@gentoo.org)
President/CEO,
Gentoo Technologies, Inc.
October 2001
С выходом релиза 2.4 Linux появилась возможность использования filesystem с новыми свойствами, таких как Reiserfs, XFS, GFS и других. Эти filesystems еще не достаточно опробованы и имеются вопросы, что именно они могут делать, насколько они хороши и насколько оправдано их использование в промышленной Linux среде. В этой статье Daniel проведет вас через процесс подготовки системы к использованию devfs. Описание процесса завершается, когда ваша система полностью готова к использованию devfs. И, конечно, предполагается еще одна статья, в которой Daniel опишет заключительную фазу установки devfs.
В предыдущей статье (часть 4) было описание того, чем является devfs и как она решает многие проблемы управления устройствами. Теперь наступило время практической реализации devfs на вашей системе. В этой статье будет описана вся подготовительная работа для devfs-ready, а в следующей - конвертация на devfs. Можно безболезненно выполнить все практические шаги из этой статьи еще до прочтения следующей, так как в результате система будет функционировать "по старому", но в полной готовности к решающему действию.
Обратите внимание: поскольку здесь выполняются достаточно фундаментальные замены частей Linux системы, не исключена возможность возникновения тупиковых ситуаций. Будет хорошей идеей отработать шаги на некритическом Linux box (по крайней мере, в первый раз).
Чтобы иметь работающую devfs требуется Linux 2.4 (статья ориентирована на 2.4.6 или 2.4.8) и glibc 2.1.3 или современней. Рекомендуется Xfree86 не ниже 4.0 и будет не лишним сначала модернизироваться до Xfree86 версии 4.1.
Необходимая предосторожность - освойте bash rescue.
В этой статье предлагается внести изменения в boot-critical части Linux
системы. Любые ошибки, скажем, по обычной невнимательности, в таких вещах могут
приводить к невозможности загрузки системы в "штатном режиме". Я обязан начать
статью с пояснения, как в неприятной ситуации загрузить bash
shell.
Надеюсь, этого не потребуется и все же... Если система не загружается из-за
проблемы в init
scripts или даже непосредственно в
/sbin/init
, повода для волнений еще нет.
Самый простой способ выполнить emergency boot - передать опцию
init=/bin/bash
ядру в паузе boot-time, сделанных GRUB или
LILO. В случае с GRUB вы должны передавать эту опцию, в интерактивном
режиме нажав "e", и редактируя запись menu в реальном времени. В случае
с LILO есть выбор. Можно ввести параметр интерактивно в паузе загрузки или
создать "стационарную" запись для "emergency" в /etc/lilo.conf, не забыв
выполнить lilo.
Процедура "rescue" выглядит так. Сначала передается
init =/bin/bash
ядру в качестве опции начальной загрузки. В
процессе начальной загрузки вместо обычного первого процесса /sbin/init
будет запущен /bin/bash
. Вы увидите bash
root prompt без всякого log in:
#
При этом, несмотря на наличие root bash
prompt, смонтирована
только файловая система root, и та в режиме read-only. От этого пункта двигаемся
дальше. Если файловые системы не размонтированы чисто, требуется сначала
прогнать fsck
. Начните с fsck -a
на root файловой
системе, а затем fsck -R -A -a
на всех остальных:
# fsck -a /dev/hda1
# fsck -R -A -a
Теперь, когда метаданные на ваших файловых системах находятся в непротиворечивом состоянии (либо предыдущий шаг был пропущен вследствие предшествовавшего "чистого размонтирования" или использования журналируемых файловых систем), можно перемонтировать root файловую систему в read-write и монтировать /proc:
# mount / -o remount,rw
# mount /proc
После этого монтируйте остальные требующиеся деревья файловой системы, находящиеся на отдельных partitions. Например, для монтирования /usr:
# mount /usr
Может оказаться полезным активизировать swap, если планируется делать что-нибудь большее, чем запуск текстового редактора. Впрочем, даже использование emacs, может потребовать наличия swap:
# swapon -a
Пришло время запустить любимый редактор и устранить проблему с начальной загрузкой. Повторно перемонтируйте partitions в режим read-only, способом, аналогичным их монтированию. Например, если /usr находится на отдельном partition, то, для приведения файловой системы в непротиворечивое состояние перед перезагрузкой, выполните:
# mount /usr -o remount,ro
# mount / -o remount,ro
Теперь перезагрузка произойдет без запуска fsck
. Если с помощью
редактора вы правильно решили проблему, LILO или GRUB отработают "штатно":
# /sbin/reboot -nfi
Теперь, зная действия при возникновении критической ситуации, можно подготовить
систему к переходу на devfs. В следующей статье будут описаны некоторые
достаточно сложные изменения в Linux системе. Почему это необходимо? Мы сделаем
все, кроме enabling devfs функционирования ядра (последний шаг самый простой).
До этого мы инсталлируем devfsd
(device management daemon)
в специальном режиме так, чтобы он поддержал возможность отката и восстановления
любых изменений в device permissions и ownership. Требуется немного изловчиться,
чтобы получить хорошо функционирующую новую систему. Как только это произойдет,
вы будете очень довольны результатом.
Первый шаг в переходе на devfs достаточно прост: требуется enable devfs support
в ядре. Ядро должно быть серии 2.4. Войдите в каталог с исходниками ядра и
выполните make menuconfig
или make xconfig
(по вкусу).
В секции Code maturity level options проверьте, что Prompt for
development and/or incomplete code/drivers enabled. В секции
File systems находим /dev file system support (EXPERIMENTAL).
Согласитесь с этим пунктом. Откроются еще две дополнительные опции. Первая
указывает, будет ли devfs монтироваться автоматически к /dev в процессе
начальной загрузки. От этого необходимо отказаться, мы будим монтировать /dev
вручную, используя специальный сценарий. Вторая опция, Debug devfs,
также должна быть заблокирована.
Находясь в секции File systems, отключите поддержку /dev/pts file system for Unix98 PTYs, если это еще не заблокировано. Devfs сама обеспечивает подобные функциональные возможности, а devpts в дальнейшем не потребуется. Сохраните конфигурацию, но пока не компилируйте и не инсталлируйте новое ядро. Перед переходом к следующему шагу убедитесь, что при наличии записи о /dev/pts в /etc/fstab она должна быть закомментирована, чтобы впредь, при перезагрузках, больше не монтировалась.
Загрузите в редактор файл /etc/securetty. Этот файл используется
login
и позволяет перечислить allows tty
's, т.е.
разрешенные для входа в систему пользователем root. В нем обычно перечислены
устройства от tty1
до tty12
, по одному на строку.
Чтобы файл подготовить для devfs, необходимо добавить devfs-style имена для
своих tty's, сохранив старые на случай загрузки с devfs disabled. Добавьте
следующие строки после старых записей в /etc/securetty.
vc/1
vc/2
vc/3
vc/4
vc/5
vc/6
vc/7
vc/8
vc/9
vc/10
vc/11
vc/12
Следующим шагом инсталлируем в системе devfsd
(devfs helper daemon).
Devfsd позаботиться о создании "old-style" compatibility device nodes,
автоматизации действий, связанных с registered/unregistered драйверов,
запоминания изменений в правах и владельцах специальных файлов на файловой
системе root и т.п. В данный момент требуется только сама инсталляция, а в
следующей статье научимся ее использовать вместе с devfs. Загрузим с ftp самую
современную версию devfsd
tarball (см. Resources). На момент написания статьи это была 1.3.16.
Выполним следующее:
# tar xzvf devfsd-1.3.16.tar.gz
# cd devfsd
# make
Devfsd откомпилирован и готов к инсталляции. Если man pages хранятся в
/usr/man, выполните make install
, а если используете
FHS-compliant и man pages находятся в /usr/share/man, то выполните
make mandir=/usr/share/man install
. Devfsd теперь инсталлирован,
но не в рабочем состоянии (именно то, что на данный момент и требуется).
Примечание по конфигурации.
Мы будем конфигурировать |
Теперь пришло время скомпилировать и инсталлировать ядро (которое ранее было сконфигурировано). Это ядро должно подменить ваше текущее. Оно должно загрузиться как обычное, хотя и имеет встроенную поддержку devfs. Вы не должны заметить отличий в их функционировании. После инсталляции убедитесь, что после перезагрузки все работает прекрасно.
Теперь система готова к конвертированию devfs, что является темой следующей статьи. Но, сначала, познакомимся с самим подходом к конвертированию. Как будет показано, devfs-enabling дистрибутив может быть очень хитрым, особенно, если есть желание использовать удобные features, например, persistent permissions и ownership.
Проблемы с kernel automounting
Имеется несколько способов devfs-enable. Первый - иметь ядро с поддержкой
автоматического монтирования devfs к /dev в процессе начальной загрузки
(помните? Мы отказались от этой опции). На первый взгляд, такой подход наиболее
предпочтителен, так как гарантирует, что все devfs-style devices доступны всем
процессам, включая /sbin/init
. Однако при таком подходе имеются
и проблемы. Если devfs обеспечивает все "new-style" devices, то old-style device
nodes создаются devfsd
daemon. Devfsd не запускается ядром, и,
если мы имеем kernel mount devfs at boot, мы окажемся с не
смонтированными device nodes ко времени запуска /sbin/init
. Из
этого следует, что, отработав до system initializations scripts, процесс
загрузки потребует старта devfsd
одним из первых. Хитрость не
только в этом (требуется детальное понимание взаимодействия startup scripts на
конкретной системе). Такой подход порождает другие проблемы.
Основная проблема с kernel mounting состоит в том, что devfsd
оптимизирован для работы, когда он имеет доступ к содержимому "оригинального"
old-style on-disk /dev каталогу. Обычное решение - allow access к "оригинальным"
old-style devices через bind-mounting /dev к другой точке (обычно
/dev-state) до того, как devfs монтируется к /dev.
Такое решение гарантирует, что содержимое старого каталога /dev все еще
доступно в /dev-state после монтирования devfs. При таком подходе
devfsd
может использовать этот каталог для persistent device
storage. Важно понять, что без bind mount старое содержимое /dev становится
недоступным сразу после монтирования devfs к /dev. В этом суть проблемы при
использовании kernel mount devfs. Если ядро монтирует файловую систему
devfs к /dev до старта любого процесса, способного выполнить bind mount, то
содержимое "оригинального" /dev становится полностью недоступным. Неприятность,
не так ли? (О bind mounts было рассказано в части 3
этого цикла.)
В идеале хотелось бы иметь полный набор device nodes (new-style и old-style
для обратной совместимости) еще до старта /sbin/init
, а также
возможность выполнить bind mount /dev к другой точке перед монтированием devfs.
Но возможно ли это?
Одно из возможных решений - добавление специального kernel patch, чтобы
выполнить bind mount от /dev к /dev-state. Но, при таком решении проблемы
загрузки, создаются неудобства, связанные с необходимостью вручную править
исходники каждого нового Linux ядра перед его компиляцией и инсталляцией.
Имеется альтернативный (по мнению автора - лучший) способ решения проблемы
"курица или яйцо" для devfs, через использование init wrapper. Для этого
конкретного случая init wrapper реализован как bash
script,
который "подставляется" вместо /sbin/init
(а реальный init
переименовывается в /sbin/init.system). Коротко о том, что делает
init wrapper:
#!/bin/bash
mkdir -f /dev-state
mount --bind /dev /dev-state
mount -t devfs none /dev
devfsd /dev
exec /sbin/init.system
Первое, wrapper гарантирует, что /dev-state существует. Второе, /dev tree
через bind mount перемонтируется к /dev-state для доступности содержимого /dev
из каталога /dev-state. Третье, монтируется файловая система devfs к вершине
/dev, и, четвертое, стартует devfsd
так, что old-style устройства
автоматически регистрируются одновременно с devfs. Последнее, через команду
exec
стартует "оригинальный" /sbin/init
, который
заблаговременно был переименован в /sbin/init.system
. Команда
exec
осуществляет "обратную подмену" bash
script
на init.system
. Из этого следует, что bash
script
завершается, а его идентификатор (ID 1) наследуется init.system
(идентификатор, требуемый для процесса init). Когда /sbin/init.system
запускается, начальная загрузка системы происходит как обычно за исключением
того, что devfs уже полностью в рабочем состоянии. Использование init wrapper
позволило отказаться от kernel patch или иметь дело с devfs системой,
имеющей ограниченную обратную совместимость (kernel devfs automount).
В следующей статье будет описание процесса получения full версии init wrapper и
примеры использования преимуществ многих мощных devfsd
's features.
About the authorResiding in Albuquerque, New Mexico, Daniel Robbins is the President/CEO of Gentoo Technologies, Inc., the creator of Gentoo Linux, an advanced Linux for the PC, and the Portage system, a next-generation ports system for Linux. He has also served as a contributing author for the Macmillan books Caldera OpenLinux Unleashed, SuSE Linux Unleashed, and Samba Unleashed. Daniel has been involved with computers in some fashion since the second grade, when he was first exposed to the Logo programming language as well as a potentially dangerous dose of Pac Man. This probably explains why he has since served as a Lead Graphic Artist at SONY Electronic Publishing/Psygnosis. Daniel enjoys spending time with his wife, Mary, and his daughter, Hadassah. You can contact Daniel at drobbins@gentoo.org. Перевод: Владимир Холманов |