Обслуживание периферии в коде модулей ядра

Часть 49. Подсистема udev

Comments

Серия контента:

Этот контент является частью # из серии # статей: Обслуживание периферии в коде модулей ядра

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Обслуживание периферии в коде модулей ядра

Следите за выходом новых статей этой серии.

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

Подсистема udev

Подсистема udev — это подсистема создания именованных устройств, которая заменила подсистему devfs (или статическое отображение устройств в каталог /dev), унаследованную первыми версиями Linux от оригинальных UNIX-систем. Подсистема udev по мере подключения создаёт в каталоге /dev динамические имена только для тех устройств, которые реально присутствуют на данный момент в системе. Она является надстройкой пространства пользователя над файловой системой ядра /sys, которая подробно рассматривалась в предыдущих частях (части 28 и 29). Задача ядра состоит в определении изменения в аппаратной конфигурации системы (например, для устройств горячего подключения и USB) и регистрации этих изменений путём добавления записей в каталог /sys. Задача подсистемы udev — выполнить дальнейшую интеграцию и настройку такого устройства в системе (т.е. отобразить его в каталоге /dev) и предоставить пользователю уже готовое к работе устройство.

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

Ядро посылает асинхронные уведомления о любых изменениях в подсистему /sys через дэйтаграммный сокет с помощью специально спроектированного протокола netlink.

fd = socket( AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT );

Получив такое уведомление от ядра, демон udevd (но это может делать и любой процесс пространства пользователя) может проанализировать дерево /sys (на основе полученных из содержимого дэйтаграммного уведомления параметров) и динамически (по событию) создать соответствующее имя в /dev. Как видно, всё достаточно просто. Более того, поскольку всё это (после получения уведомления) происходит в пространстве пользователя (а не в ядре), то при создании имени в каталоге /dev можно применить развитую систему правил, определяющих параметры имени, присваиваемому устройству. Эти правила могут формироваться пользователем и храниться в обычных текстовых файлах.

Подсистема udev настраивает устройства в соответствии с заданными правилами. Правила содержатся в файлах в каталоге /etc/udev/rules.d/ (также файлы с правилами могут содержаться и в каталоге /etc/udev/). Все файлы правил просматриваются и применяются в алфавитном порядке.

$ ls /etc/udev/rules.d/
05-udev-early.rules  51-hotplug.rules  60-pcmcia.rules  61-uinput-stddev.rules  
	90-dm.rules           bluetooth.rules
40-multipath.rules   60-libsane.rules  60-raw.rules     61-uinput-wacom.rules   
	90-hal.rules
50-udev.rules        60-net.rules      60-wacom.rules   90-alsa.rules           
	95-pam-console.rules
$ cat 60-raw.rules
...
# An example would be:
#   ACTION=="add", KERNEL=="sda", RUN+="/bin/raw /dev/raw/raw1 %N"
...

Информацию по подсистеме udev можно получить из справочника man:

$ man udev
UDEV(7)                              udev                              UDEV(7)
NAME
       udev - dynamic device management
...

Там же можно найти информацию о синтаксисе написания правил для устройств. С помощью этих правил можно определить:

  • динамическое создание имени, соответствующего устройству в /dev;
  • права доступа к этому имени;
  • запуск дополнительных (конфигурирующих) процессов при подключении этого устройства и т.д.

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

$ udevadm info -q path -n sda
/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
$ udevadm info -a -p $(udevadm info -q path -n sda)
...
looking at device '/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda':
    KERNEL=="sda"
    SUBSYSTEM=="block"
...
$ udevadm info -h
Usage: udevadm info OPTIONS
  --query=<type>             query device information:
      name                     name of device node
      symlink                  pointing to node
      path                     sys device path
      property                 the device properties
      all                      all values
  --path=<syspath>           sys device path used for query or attribute walk
  --name=<name>              node or symlink name used for query or attribute walk
...

В процессе разработки драйвера важно определить значения параметров, использовавшиеся в правилах для подключения и отключения конкретного устройства, для которого предназначается драйвер. Эти значения можно увидеть, если выполнить физическое отключение-подключение устройства при работающей программе мониторинга уведомлений:

$ udevadm monitor --property --kernel 
monitor will print the received events for: 
KERNEL - the kernel uevent 

KERNEL[27478.580340] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 (usb) 
ACTION=add 
BUSNUM=001 
DEVNAME=/dev/bus/usb/001/035 
DEVNUM=035 
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4 
DEVTYPE=usb_device 
MAJOR=189 
MINOR=34 
PRODUCT=1307/163/100 
SEQNUM=3186 
SUBSYSTEM=usb 
TYPE=0/0/0 

KERNEL[27478.580711] add     
	 /devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 (usb) 
ACTION=add 
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.4/1-4.4:1.0 
DEVTYPE=usb_interface 
INTERFACE=8/6/80 
MODALIAS=usb:v1307p0163d0100dc00dsc00dp00ic08isc06ip50 
PRODUCT=1307/163/100 
SEQNUM=3187 
SUBSYSTEM=usb 
TYPE=0/0/0 
...

В данном листинге показан только начальный вывод, охватывающий два первых асинхронных уведомления от ядра (например, для реальных USB-устройств их может быть значительно больше: 5, 10 или более фаз установки устройства). Представленные строки отображают имена и значения параметров, посылаемых в уведомлении:

  • ACTION=add — происходит подключение устройства;
  • MAJOR=189, MINOR=34 — старший и младший номера устройства в /dev;
  • PRODUCT=1307/163/100 — индексы VID:PID для подключаемого устройства, упоминавшиеся в предыдущей части.

Именно из этих именованных параметров и их значений конструируются текстовые файлы, хранящиеся в каталоге /etc/udev/rules.d/ и предписывающие выполнить те или иные действия при поступления уведомления от ядра с указанными параметрами.

Заключение

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

К статье прилагается архив udev.tgz, который можно найти в разделе "Материалы для скачивания", не имеющий прямого отношения к коду модуля, но демонстрирующий, как любой пользовательский процесс может получать асинхронные уведомления о событиях ядра. Приложение mondev регистрирует уведомления о горячих подключениях-выключениях устройств, а приложение monitor отслеживает уведомления об изменениях в состояниях сетевых интерфейсов. Изучение этих приложений поможет лучше понять, как драйверы устройств взаимодействуют с ядром.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=857978
ArticleTitle=Обслуживание периферии в коде модулей ядра: Часть 49. Подсистема udev
publish-date=02142013