Еще раз про udev

Алексей Федорчук

http://alv.me/

17 Июнь 2009 г

Несколько лет назад, почти сразу после внедрения в Linux механизма udev, я написал краткую заметку по поводу первых разборок с оным. Нынче, в связи со вновь образовавшимися обстоятельствами, настало время опять обратиться к этой теме, расширив и даже, как сказал бы один из наших президентов, углубив её. Прежде чем начать настоящую заметку, оговорюсь, что в неё включён весь материал заметки прежней — тот, что сохранил актуальность. Так что обращаться к последней необходимости нет — разве что в историческом аспекте.

Udev — это механизм поддержки настраиваемого динамического именования устройств в Linux, пришедшая на смену виртуальной файловой системе устройств devfs; во FreeBSD эта функция возлагается на последнюю. Первый и основной разработчик udev – Грег Кроа-Хартман (Greg Kroah-Hartman).

В отличие от devfs, udev — не файловая система, поддерживаемая ядром, а обычная пользовательская программа. Для своего функционирования udev нуждается в виртуальной файловой системе — sysfs (о которой существует подробная статья Владимира Попова). Основываясь на информации из неё, udev и присваивает имена различным устройствам, в том числе и при горячем их подключении.

Как известно, любой POSIX-системе имена конкретных устройств более или менее безразличны, так как оперирует она не с ними, а с их идентификаторами. Ранее, до внедрения devfs и, позднее, udev, в качестве таковых выступали так называемые номера устройств — старший номер устройства, определяющий его класс (например, ide-накопители) и младший его номер, указывающий на конкретный экземпляр данного представителя класса. Ныне же используются непосредственные идентификаторы устройств — серийный номер винчестера, его положение на SATA-разъёме или канале PATA-шины, и так далее. Сочетание их для каждого диска (раздела, и так далее) оказывается уникальным. Так вот, udev извлекает эти сведения из файловой системы sysfs и, руководствуясь определенными правилами, ставит им в соответствие “человеческие” имена (вроде тех же /dev/sda и так далее).

Процесс включения поддержки udev очень прост и сводится к установке пакета udev — во всех современных дистрибутивах Linux он входит в базовую систему, так что специально его устанавливать не нужно.

Далее, следует позаботиться о запуске демона udevd при старте системы. За это отвечает один из сценариев инициализации, зависящий от дистрибутива. Например, в Ubuntu это будет файл /etc/init.d/udev. Впрочем, в любом современном дистрибутиве это также происходит по умолчанию, так что руками ничего править не надо.

Теперь в каталоге /dev можно видеть привычные имена файлов устройств — /dev/sda, соответствующее винчестеру на первом разъёме SATA, /dev/sda[1-4] для его разделов, а также /dev/sr0 для CD-привода; имеется и традиционный файл устройства /dev/cdrom — символическая ссылка на /dev/sr0:

$ ls -l /dev/cdrom lrwxrwxrwx 1 root root 3 2009-05-19 08:27 /dev/cdrom -> sr0 Подключение флэш-накопителя в USB-разъем немедленно приводит к появлению в списке устройства с именем /dev/sdb, не меняющееся, сколько бы ни повторять эту процедуру. Иными словами, каталог /dev приобретает вид, привычный по временам статического именования устройств. С той только разницей, что теперь он не заполнен впрок файлами возможных, но не существующих устройств.

За конфигурирование механизма udev отвечает специальный файл — /etc/udev/udev.conf, определяющий глобальные параметры, корневой каталог для файлов устройств (по умолчанию – /dev), файл базы данных устройств, файлы описания правил именования устройств и прав доступа к ним, а также правила создания символических ссылок (подобных /dev/cdrom). Конкретные имена этих файлов и их местоположение зависят от дистрибутива. Обычно это файлы вида /etc/udev/rules.d/udev.rules и /etc/udev/permissions.d/udev.permissions.

Ручное вмешательство в конфигурационные файлы требуется редко, но иногда такая необходимость возникает. Так, на заре внедрения механизма udev я столкнулся (в дистрибутиве Archlinux) с такой ситуацией: после перезапуска машины с задействованным udev у меня исчез звук — и с первого же взгляда на файл /etc/udev/permissions.d/udev.permissions стало ясно, почему. Права доступа ко всем аудио-устройствам имели примерно такой вид:

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

Для управления механизмом udev “на лету” служит утилита udevadm. В частности, с её помощью можно определить уникальные идентификаторы любых устройств — в современных дистрибутивах, как уже было сказано, именно они используются, например, для автоматического монтирования файловых систем при старте машины. Для этой цели следует дать команду udevadm примерно в таком виде:

$ udevadm info —query=env —name=/dev/sdb1 | grep UUID Здесь субкоманда info предписывает вывести информацию, опция –query определяет, какую именно (env — спецификации устройства), а значением опции –name будет имя файла устройства. Среди множества параметров, таких, как модель диска, его интерфейс и многое другое, будет и искомый идентификатор устройства примерно такого облика (именно его мы отфильтровываем, передавая вывод утилиты udevadm команде grep): ID_FS_UUID=56b2dede-e113-425a-9f50-c1017f9e9113 Этот идентификатор можно использовать в файле /etc/fstab вместо имени устройства, примерно таким образом: # / was on /dev/sda6 during installation UUID=f65d488b-a4c0-455c-9372-34bbbae2f5c1 / ext4 relatime 0 1 Что имеет и свои недостатки, и свои достоинства. Недостатки — очевидны: громоздкость и неудобочитаемость файла. Достоинства не лежат на поверхности, но также имеют место быть: в частности, при переключении дисков с одного SATA-разъема на другой, или при смене последовательности обращения к винчестерам в BIOS Setup, не нужно думать об изменении соответствующих строк в /etc/fstab.

Ещё одна напрашивающаяся сфера применения UUID — обеспечение безопасности. Так, внесением в /etc/fstab строк вида

UUID=значение /mountpoint vfat noauto,user 0 0 можно разрешить монтировать от лица обычного пользователя, скажем, не флэш-накопители вообще, а только совершенно конкретные флэшки. То же самое можно распространить на CD- и DVD-носители, камеры etc. Способ довольно хлопотный — потребуется вносить много строк в /etc/fstab и отключать автомонтирование сменных накопителей через HAL (о котором речь пойдёт в следующем разделе). Однако можно представить себе ситуации, когда он будет оправдан. Одна из дополнительных особенностей udev — возможность создавать файлы устройств с нестандартными именами, например, /dev/camera — для цифрового фотоаппарата, /dev/flash — для флэш-накопителя, и так далее. Это полезно, в частности, если одновременно подключено несколько устройств с интерфейсом одного типа — скажем, та же камера и флэшка, поскольку не нужно знать, какое из имен файлов устройств вида /dev/sd?# чему соответствует.

Рассмотрим этот вопрос на примере обычного флэш-накопителя с USB-интерфейсом. Для чего подключаем интересующее нас устройство и в с помощью всё той же команды udevadm определяем его идентификатор:

$ udevadm info —query=env —name=/dev/sdb1 | grep UUID ID_FS_UUID=D3B2-6597 Теперь нам понадобятся права администратора для создания файла описания правил, получаемый, например, так: $ sudoedit /etc/udev/rules.d/00-flash.rules После ввода пользовательского пароля мы оказываемся в редакторе по умолчанию, определяемом значением переменной EDITOR данного пользователя (у меня это nano); если таковая не определена, будет вызван стандартный vi. В открытый в нём пустой файл (имя его произвольно, важно только проследить, чтобы он считывался раньше стандартных для данного дистрибутива файлов описаний правил), вносим единственную строку ID_FS_UUID=”D3B2-6597″, NAME=”fl256″ где значением переменной ID_FS_UUID будет полученный выше идентификатор устройства, значением переменной NAME — какое-либо мнемонически удобное имя, в данном случае символизирующее, что мы имеем дело с флэшкой объёмом 256 Мбайт. Перезагрузки системы не потребуется: для проверки правильности выполненных действий достаточно отсоединить устройство и подключить его заново.

Конфигурационные файлы udev при этом будут перечитаны, в результате чего в каталоге /dev/ появится файл с соответствующим именем:

$ ls /dev/fl* /dev/fl256 Повторяем процедуру для всех интересующих нас устройств: так, я проделываю это для постоянно используемых мной флэшек объемом 1 Гбайт и 16 Гбайт, определяя для них имена fl1g и fl16g, соответственно. С камерой всё точно также, однако разнообразия ради проделаем описанную процедуру несколько иным путём, а именно: подключаем камеру и даём команду devadm в несколько иной форме:

$ udevadm info —query=env —path=/block/sdd/sdd1 | grep MODEL ID_MODEL=Samsung_Digital_Camera После чего в файл /etc/udev/rules.d/00-flash.rules добавляем соответствующую строку: ID_MODEL=”Samsung_Digital_Camera”, NAME=”camera” И после отключения и повторного присоединения устройства имеем счастье наблюдать в каталоге /dev новый файл: $ ls -l /dev/camera brw-rw—— 1 root disk 8, 49 2009-05-20 08:38 /dev/camera Ещё один способ придать файлам устройств имена, отличные от присваиваемых ядром — использование символических ссылок. Это целесообразно, в частности, для файлов устройств компакт- и DVD-приводов: ряд программ, например, Mplayer, при проигрывании аудио-, видео-CD и DVD по умолчанию рассчитывает обнаружить их в устройствах типа /dev/cdrom и /dev/dvd. Поскольку файлы устройств создаются динамически при загрузке системы, то и ссылки должны создаваться динамически, что также описывается соответствующими правилами. В большинстве современных дистрибутивов Linux’а такие правила задаются по умолчанию при инсталляции системы. Так, в Ubuntu они содержатся в файле /etc/udev/rules.d/70-persistent-cd.rules в следующем виде:

ENV{ID_CDROM}==”?*”, ENV{ID_PATH}==”pci-0000:00:1f.5-scsi-1:0:0:0″, SYMLINK+=”cdrom”, ENV{GENERATED}=”1″ ENV{ID_CDROM}==”?*”, ENV{ID_PATH}==”pci-0000:00:1f.5-scsi-1:0:0:0″, SYMLINK+=”cdrw”, ENV{GENERATED}=”1″ ENV{ID_CDROM}==”?*”, ENV{ID_PATH}==”pci-0000:00:1f.5-scsi-1:0:0:0″, SYMLINK+=”dvd”, ENV{GENERATED}=”1″ ENV{ID_CDROM}==”?*”, ENV{ID_PATH}==”pci-0000:00:1f.5-scsi-1:0:0:0″, SYMLINK+=”dvdrw”, ENV{GENERATED}=”1″ Если по каким-либо причинам ссылок вида /dev/cdrom -> /dev/sr0 при старте системы не создаётся, следует прописать правила, по образу и подобию приведённых, вручную.

Добавить комментарий

Войти с помощью: