О блоге

Все новые материалы размещаются на Блогосайте alv.me. Старые - в процессе переноса.

29.07.2008

Кратко о udev

Citkit, 23 августа 2005 г


Внедрение в Linux файловой системы устройств - devfs - было шагом, безусловно, прогрессивным. Не знаю, насколько оно облегчило жизнь разработчикам драйверов устройств - ради которых весь сыр-бор и затевался, насколько я понимаю, - но и пользователи получили свои плюсы. В частности, при работе с устройствами горячего подключения, коих нынче развелось немало (всякого рода флэш-драйвы, цифровые камеры и т.д.).

Однако любой прогресс - штука неоднозначная, и чем-то за него расплачиваться приходится. В данном случае первый счет был предъявлен в виде крайне неуклюжей системы наименования устройств: вместо простого и понятного /dev/hda1 для первого раздела на первом физическом диске мы получили жутковатые конструкции типа /dev/ide/host0/bus0/target0/lun0/part1. И даже механизм символических ссылок вроде /dev/discs/disc0/part1 (что являет собой симлинк на вышеуказанный адрес) не очень облегчил дело. А реализация обратной совместимости именования устройств через соответствующего демона - devfsd - требовала дополнительных телодвижений (не для всех устройств - абсолютно тривиальных), да и загромождает каталог /dev до невозможности восприятия. Как тут было не позавидовать пользователям FreeBSD 5-й ветки, которые, в силу ряда причин, обратной совместимостью могли не заморачиваться. И где все содержимое каталога /dev умещается на половине стандартной консольной страницы...

Были и некоторые иные неудобства в Linux-реализации devfs. В частности, меня больше всего доставало следующее. Как известно, в POSIX-системах большинство накопителей с интерфейсами, не являющимися нормальным IDE (ATAPI), предстают перед пользователем через девайс ass (пардон, scsi, конечно же). В частности - те же USB-флэшки, которыми я пользуюсь постоянно. И причем, в силу специфики работы, вынужден их постоянно менять.

Что происходит в этом случае? Воткнув флэшку первый раз, мы видим в файловой систем устройств появление нового файла - /dev/scsi/тра_та_та/disc. Или, в зависимости от схемы разбиения, то же самое с окончанием на part1 или part4 (почему всякого рода сменные накопители, начиная с zip-дисков, фабрично часто разбиваются как 4-й primary partition - тайна сия велика есть).

Разумеется, истинный POSIX'ивист, закосневший в смертном грехе лености, быстро избавит себя от необходимости набора столь длинного пути при монтировании флэшки. Внеся в файл /etc/fstab строку типа

/dev/scsi/host0/bus0/target0/lun0/disc /mnt/usb \
vfat user,noauto,umask=022 0 0

или, в предположении, что вкрученный винчестер у него один,

/dev/discs/disc1/disc /mnt/usb vfat \
user,noauto,umask=022 0 0

Любая из которых, кроме всего прочего, позволит выполнять эту операцию от лица обычного пользователя и получать нормальные (без бита исполнения) права доступа для файлов на сменном носителе. И наступит ему счастье...

...До того, правда, момента, как не потребуется ему эту флэшку вынуть и вставить другую (да хотя бы и ту же самую). Каковая тут же волшебным образом превратится в устройство с именем /dev/discs/disc2/disc, и попытка смонтировать его тем же образом закончится сообщением об отсутствии такого устройства в /etc/fstab или /etc/mtab. Конечно, ручному монтированию это не помешает, но придется а) проводить его уже от лица root'а и б) маску доступа впечатывать с клавиатуры.

Как-то раз давеча, повозившись с тремя флэшками, сменяемыми раз по пять в час, решил я установить у себя udev, которая, в числе прочего, обещает и избавление пользователя от этой докуки.

Что такое udev? Человеческим языком выразить затрудняюсь. Могу только процитировать соответствующее определение с man-страницы в своем вольном переводе. Так вот, согласно man (8) udev, это - поддержка настраиваемого динамического именования устройств в Linux (насколько я знаю, в других Unix-like ОС такого понятия до сих пор не было, за BSD-системы могу говорить определенно).

В отличие от devfs, udev - не новая поддерживаемая ядром файловая система, пусть и виртуальная, а обычная пользовательская программа. Более того, при ее использовании необходимость в поддержке devfs как будто бы отпадает вообще.

Правда, для своего функционирования udev нуждается в еще одной виртуальной файловой системе - sysfs, но ее поддержка в ядрах серии 2.6.X осуществляется автоматически (а сама эта файловая система монтируется по умолчанию в каталог /sys). Основываясь на информации из которой, udev и присваивает имена всяческим устройствам (в том числе и при горячем их подключении).

Как известно, любой POSIX-системе имена конкретных устройств более или менее безразличны, так как оперирует она не с ними, а с их идентификаторами. Ранее, до внедрения devfs (и, тем более, udev), в качестве таковых выступали т.н. старший номер устройства, определяющий класс оных (например, ide-накопители) и младший его номер, указывающий на конкретный экземпляр данного представителя класса. Ныне же в ход пошли непосредственные идентификаторы устройств - - сериальный номер винчестера, его положение на канале IDE-шины, и так далее, сочетание которых для каждого диска (раздела, и так далее) оказывается уникальным. Так вот, udev извлекает эти сведения из файловой системы sysfs и, руководствуясь определенными правилами, ставит им в соответствие "человеческие" имена (вроде тех же /dev/hda и так далее).

В двух предыдущих абзацах я в меру своего разумения пересказал прочитанное - в частности, в Udev FAQ с kernel.org. И, возможно, пересказал не вполне понятно. Вот и я мало чего из прочитанного понял, пока не поставил себе udev. Благо, процесс этот очень прост и сводится к трем действиям:

  • установке пакета udev;
  • запрещению монтирования devfs при старте системы;
  • разбирательству с тем, что же получилось в результате.

Установка udev выполняется точно так же, как и любой другой программы - сборкой из исходников или штатными средствами имеющегося дистрибутива. В частности, в Archlinux, которым я пользуюсь в данный момент, udev входит в состав умолчального базового комплекта (если устанавливать current-версию по FTP).

Запретить монтирование devfs можно также обычным образом - передачей ядру соответствующего параметра, руками при старте системы, или в конфиге загрузчика. Для lilo требуется добавить в файл /etc/lilo.conf строку вида

append="devfs=nomount"

где-нибудь после описания образа ядра и корневого раздела. В grub параметр devfs=nomount вписывается в строку указания образа и корня:

kernel (hd0,0)/boot/vmlinuz-up \
root=/dev/hda1 devfs=nomount

При использовании lilo следует не забыть перезапустить эту команду, и в обоих случаях требуется перезагрузка. По успешном (надеюсь) завершении которой можно пользоваться прелестями udev.

А прелести эти я смог оценит в полной мере. Дело в том, что до этого у меня devfsd был настроен для обеспечения обратной совместимости по самому минимуму. То есть никаких /dev/hda в виде ссылок не было - ссылки создавались только для самых необходимых устройств (/dev/dsp и тому подобных, без которых не работали аудиоприложения). Так что мой каталог /dev, не считая вложенных подкаталогов типа /dev/ide, dev/discs, dev/cdroms и так далее, был почти пуст.

Теперь же в каталоге /dev можно было видеть полузабытые имена - /dev/hda, соответствующее моему винчестеру, и /dev/hda[1-4] для его разделов, а также /dev/hdc для CD-привода. Причем это были именно реальные файлы устройств, а сохранившиеся /dev/ide/host0/bus0/target0/lun0/disc и так далее - волшебным образом превратились в символические на них ссылки.

Втыкание флэшки в USB-разъем немедленно приводило к появлению в списке устройства с именем /dev/sda, не менявшимся, сколько ни повторяй эту процедуру.

Иными словами, каталог /dev приобрел вид, привычный по до-devfs'ным временам. С той только разницей, что он не был забит файлами возможных, но не существующих устройств.

Будучи воспитанным во времена исторического материализма (а также всяких прочих "измов"), в волшебство я, естественно, не уверовал. И задался вопросом - как же такое случилось? Для чего пришлось влезть в конфигурационные файлы программы udev.

Их оказалось не так и много. Во-первых, это был /etc/start_udev - скрипт, запускающий программу udev при старте системы.

Далее, в том же каталоге /etc обнаружился еще и специальный подкаталог - /etc/udev, где собственно и были собраны конфиги программы. Главный из них - /etc/udev/udev.conf, определяющий глобальные параметры, такие, как:

  • корневой каталог для файлов устройств (по умолчанию - /dev);
  • файл базы данных устройств - /dev/.udev.tdb;
  • адрес файлов описания правил именования устройств и прав доступа к ним - /etc/udev/rules.d/ и /etc/udev/permissions.d/, соответственно;
  • имена двух сценариев, собственно и осуществляющих именование устройств - /etc/udev/ide-devfs.sh и /etc/udev/scsi-devfs.sh, вполне прозрачного назначения;
  • атрибуты принадлежности и доступа, по умолчанию присваиваемые файлам устройств при их создании.

База данных оказалась неудобопонятным бинарником, сценарии именования я проглядел любопытства ради (вряд ли стоит что-то менять в них), а вот файлы описания правил (/etc/udev/rules.d/udev.rules) и определения прав доступа (/etc/udev/permissions.d/udev.permissions)заслуживали пристального внимания.

Из рассмотрения первого файла становится ясным, каким образом создаются имена файлов устройств и символические ссылки на них (на деталях задерживаться не буду, они подробно описаны в udev (8) man). Второй же файл потребовал немедленного ручного вмешательства. Дело в том, что после перезапуска машины с задействованным udevя лишился звука - и с первого же взгляда на файл /etc/udev/permissions.d/udev.permissions стало ясно, почему. Права доступа ко всем аудио-устройствам имели примерно такой вид:

dsp*:root:root:0660

где dsp - имя устройства, root:root - хозяин и группа, соответственно, 0660 - маска, определяющая запрещение доступа для всех, кроме хозяин и группы. У меня же ранее устройства, связанные с воспроизведением аудио, относились к группе sound, в которую я и включал себя, любимого.

Так что пришлось срочно заменить второе вхождение root'а на группу sound - и после перезапуска со звуком все стало нормально.

И даже более того - побочным следствием этой процедуры стала (возникшая сама собой, и - абсолютно непонятным образом) возможность запуска моего старого RealPlayer'а (утащенного с диска OpenOffice/Mozilla производства Altlinux, 2001-й, если не ошибаюсь, год розлива - более поздние версии воспроизводят мои Real'ные остатки старых авторов кое-как, или совсем никак) из под KDE - до того он категорически отказывался это делать, апеллируя к невозможности доступа к устройству /dev/dsp.

Вот пока и все мои впечатления о udev. Как можно понять из предшествующего изложения - вполне благоприятные: с переходом на новую систему именования устройств жить на самом деле стало лучше, стало веселей. Ни с какими проблемами я вроде бы не столкнулая. Единственно, что осталось придумать, как создавать ссылку /dev/cdrom->/dev/hdc: ведь Mplayer при прокручивании кина с Video-CD или DVD почему-то жить не может без первого файла. Надеюсь со временем придумать - когда возникнет необходимость.