← Linux: загрузка
10 мин · средне · Урок 6 из 7

udev: обнаружение устройств

udev: как система находит устройства и наполняет /dev.

Где мы в цепочке загрузки

К этому моменту система уже прошла путь firmware -> загрузчик -> kernel (ядро) -> initramfs. На UEFI загрузчика может и не быть: ядро с EFI stub грузится напрямую прошивкой. Дальше systemd развёл targets по зависимостям (graphical -> multi-user -> basic -> sysinit), и система поднялась.

Осталось разобраться с железом. Диски, сетевые карты, USB-флешки, звуковые чипы: для каждого устройства в каталоге /dev должен появиться узел, через который с ним работают программы. Кто и когда его создаёт?

Кто наполняет /dev

Ответ: udev. udev — это пользовательский демон (daemon, фоновый процесс), который следит за устройствами и создаёт для них узлы в /dev. Внутри systemd он живёт как сервис systemd-udevd.

$ systemctl status systemd-udevd
● systemd-udevd.service - Rule-based Manager for Device Events and Files
     Loaded: loaded (/lib/systemd/system/systemd-udevd.service; static)
     Active: active (running) since Sat 09:00:04 UTC; 2h ago

Обрати внимание на строку Active: это обычный процесс с PID, а не код внутри kernel. Ядро только сообщает о событиях, решения принимает udev в user space.

Как это работает

Когда ядро обнаруживает устройство (воткнули флешку, поднялась сетевая карта), оно отправляет событие uevent. Это сообщение о том, что устройство появилось, исчезло или изменилось. udev слушает поток таких событий.

Получив uevent, udev создаёт узел в /dev, а затем применяет правила udev: текстовые файлы, которые описывают, что делать с устройством. Через правила задают имя, права доступа, владельца, дополнительные симлинки.

$ udevadm monitor --udev
monitor will print the received events
UDEV  [1204.51] add  /devices/.../block/sdb   (block)
UDEV  [1204.53] add  /devices/.../block/sdb/sdb1 (block)

Здесь видно, как при подключении диска приходят события add, и udev на них реагирует.

Правила udev

Правила лежат в /lib/udev/rules.d/ (системные) и /etc/udev/rules.d/ (твои, они переопределяют системные). Файл — набор строк, каждая сопоставляет условия и действия.

# /etc/udev/rules.d/70-usb-serial.rules
# для USB-адаптера с таким VID:PID выставить права и добавить симлинк
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  MODE="0660", GROUP="dialout", SYMLINK+="ftdi0"

Слева от == условия сопоставления, справа от = действия. Строка выше означает: для tty-устройства от этого производителя выставить режим 0660, группу dialout и создать симлинк /dev/ftdi0. После правки правил их перечитывают:

udevadm control --reload    # перечитать правила
udevadm trigger             # прогнать события заново для уже подключённых

Правилами удобно давать сетевой карте предсказуемое имя вместо eth0, которое зависит от порядка обнаружения. Так появляются имена вроде enp3s0.

Симлинки by-uuid и by-id

Имя диска (/dev/sda, /dev/sdb) зависит от порядка обнаружения и может меняться между загрузками. Поэтому udev создаёт стабильные симлинки по UUID и серийному номеру:

$ ls -l /dev/disk/by-uuid/
lrwxrwxrwx 1 root root 10  a1b2c3d4-... -> ../../sda1
lrwxrwxrwx 1 root root 10  e5f6a7b8-... -> ../../sdb1

Именно такой UUID пишут в /etc/fstab: он не зависит от того, каким по счёту опросили диск.

Осмотреть устройство

Команда udevadm info показывает всё, что udev знает про узел: атрибуты, симлинки, значения для условий в правилах.

$ udevadm info /dev/sdb1
P: /devices/pci0000:00/.../block/sdb/sdb1
N: sdb1
S: disk/by-uuid/e5f6a7b8-1234-5678-9abc-def012345678
E: DEVNAME=/dev/sdb1
E: ID_FS_TYPE=ext4
E: ID_FS_UUID=e5f6a7b8-1234-5678-9abc-def012345678

Строки S: — симлинки, которые создал udev. Строки E: содержат переменные, которые правила могут проверять условиями (ID_FS_TYPE, ID_FS_UUID).

Две ловушки

Первое заблуждение: файлы в /dev статичные и лежат на диске. На самом деле /dev монтируется как devtmpfs в оперативной памяти и наполняется на лету при каждой загрузке.

$ mount | grep ' /dev '
devtmpfs on /dev type devtmpfs (rw,nosuid,relatime,size=...)

Второе: udev работает внутри ядра. Нет. Ядро лишь шлёт uevent, а разбирает их и создаёт узлы отдельный процесс systemd-udevd в user space (вспомни вывод systemctl status выше).

Что важно запомнить

udev — пользовательский демон, который наполняет /dev, а не часть kernel.

Ядро при появлении устройства шлёт событие uevent, udev его ловит.

Правила udev задают имя, права и симлинки; лежат в /etc/udev/rules.d/.

/dev/disk/by-uuid/ — стабильные ссылки, которые не зависят от порядка обнаружения; их и пишут в /etc/fstab.

udevadm info показывает атрибуты устройства и созданные симлинки.

Дальше — короткий квиз по треку загрузки.

Прошли материал до конца? Отметьте урок пройденным.