Daniel Robbins ([email protected])
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.
В этой статье предлагается внести изменения в 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.
Имеется несколько способов 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.