Международная конференция разработчиков
и пользователей свободного программного обеспечения

udev‭ ‬-‭ ‬реализация devfs в пользовательском пространстве

Игорь Стародумов -‭ ‬Epam Systems -‭ ‬Минск,‭ ‬Беларусь

LVEE 2008

введение

ОС Linux используется на множестве различных платформ начиная от мобильных устройств и заканчивая суперкомпьютерами.‭ ‬Количество различного оборудования постоянно растет.‭ ‬Каждое устройство использует определённые ресурсы машины.‭ ‬Linux нужен был механизм,‭ ‬который бы эти ресурсы распределял.

Существует технология Plug-and-Play для распределения ресурсов устройствам. Для‭ “‬горячего‭” ‬подключения‭ (‬без перезагрузки‭) ‬используется термин‭ «‬hotplug‭»‬.‭ ‬Первоначально о hotplug можно было говорить только в применении к USB и PCMCIA/Cardbus.‭ ‬Потом этот список был дополнен устройствами Firewire и CompactPCI,‭ ‬а в настоящее время hotplug возможен для‭ “‬нормальных‭” ‬PCI-устройств‭ (‬посредством специальных hotplug-контроллеров‭)‬,‭ ‬IDE‭ (‬некоторые контроллеры RAID‭)‬,‭ ‬SCSI,‭ ‬модулей памяти и,‭ ‬наконец,‭ ‬CPU‭!!!

драйвера устройств

Основное условие использования устройства‭ ‬-‭ ‬это существование и загрузка соответствующего модуля ядра‭ ‬-‭ ‬драйвера.‭ ‬Нет модуля‭ ‬-‭ ‬нет работоспособного устройства.

/dev

Linux унаследовал от UNIX представление устройств в виде файлов,‭ ‬находящихся в каталоге‭ ‬/dev и характеризующихся уникальным идентификаторами‭ ‬-‭ ‬числами minor и major.‭ ‬Существование таких файлов‭ ‬-‭ ‬абсолютно необходимое условие доступности устройств.‭ ‬Если программист хочет предложить свой драйвер для широкого использования,‭ ‬то использование случайно выбранного major-номера или даже вариант с его динамическим присваиванием‭ “‬не пройдет‭”‬.‭ ‬В таких случаях разработчик драйвера должен войти в контакт с разработчиками ядра Linux и получить для своего специфического устройства‭ “‬официальный‭” ‬major-номер.‭ ‬После этого для всех Linux пользователей устройство‭ (‬и только оно‭) ‬будет связано с таким major-номером.

Не так давно общепринятой практикой было‭ “‬заблаговременное‭” ‬создание таких файлов,‭ ‬зачастую без учета реального присутствия или отсутствия устройств,‭ ‬что делало каталог‭ ‬/dev необъятным.‭ ‬Кроме того,‭ ‬поскольку под номера minor/major изначально было выделено всего по байту,‭ ‬в скором времени резерв номеров должен был исчерпаться.‭ ‬Отсутствовал единый метод представления связей между драйверами‭ (‬модулями ядра‭) ‬и устройствами.‭ ‬Отсутствовал общий hotplug-механизм,‭ ‬единый для PnP-конфигурируемых устройств и устройств,‭ ‬подключаемых к независимым шинам,‭ ‬таким как USB или PCMCIA.‭ ‬Происходило загромождение виртуальной файловой системы procfs информацией,‭ ‬не имеющей отношения к процессам,‭ ‬фактически‭ ‬-‭ ‬такой,‭ ‬для хранения которой она изначально не предназначалась.

При загрузке ядра минорные значения для найденных устройств выдавались ядром в порядке возрастания.‭ ‬Возникали проблемы с устройствами одного класса когда при перезагрузках одни и те же устройства имели разные minor-значения и,‭ ‬соответственно,‭ ‬имена.‭ ‬Аналогичные проблемы возникали также и для устройств,‭ ‬которые подключались и отключались динамически.‭ ‬При каждом новом добавлении могло поменяться имя устройства‭ ‬-‭ ‬что осложняло работу с системой.

hotplug

При добавлении/удалении и других событиях,‭ ‬связанных с устройствами,‭ ‬ядро генерирует уведомления,‭ ‬которые можно перехватывать.‭ ‬Hotplug‭ – ‬это пакет,‭ ‬написанный на shell.‭ ‬При получении сообщения от ядра запускается отдельный процесс hotplug,‭ ‬который способен решать следующие задачи:

  • связывание драйверов с новыми устройствами.‭ (‬для еще не загруженных драйверов‭);
  • специфическая конфигурация драйвера‭ (‬например подкачка firmware‭);
  • специфическая конфигурация устройства‭;
  • специфическая конфигурация подсистем‭ (‬например ifconfig‭);
  • возможный запуск какого-либо приложения.

devfs

Devfs,‭ ‬или Device Filesystem,‭ ‬разработана с единственной целью предоставления нового‭ (‬более адекватного‭) ‬способа управления всеми блочными и символьными устройствами,‭ ‬заполнившими каталог‭ ‬/dev.‭ ‬Правильное конфигурирование подразумевает добавление поддержки devfs в ядро.‭ ‬Запускается ядро,‭ ‬и драйвера начинают регистрировать свои устройства для остальной части системы.‭ ‬Если это система,‭ ‬не использующая devfs,‭ ‬как и ранее,‭ ‬выполняются системные вызовы register_blkdev‭() ‬и register_chrdev‭() (‬вместе с сопровождающими вызовы major-номерами‭)‬.‭ ‬Однако,‭ ‬если devfs поддерживается,‭ ‬то драйвера для регистрации своих устройств используют новый,‭ ‬улучшенный вызов ядра,‭ ‬называемый devfs_register‭()‬.

Devfs решает некоторые проблемы и безусловно представляет собой более продвинутое решение,‭ ‬однако на данный момент объявлена устаревшей.‭ ‬Devfs имеет следующие проблемы:

  • ‎‏devfs имеет жесткую политику именования устройств,‭ ‬которая сильно отличается от классической‭;
  • ‭‬devfs создает inod’ы в режиме ядра,‭ ‬что накладывает определенные ограничения на настройки из пользовательского режима‭ (‬права доступа,‭ ‬динамическое конфигурирование,‭ ‬именование и др‭)‬.‭ ‬Частично проблемы именования решаются с помощью линков‭; ‬однако,‭ ‬по хорошему,‭ ‬такие вещи как политика именования устройств должны выносится из ядра‭;
  • ‏devfs хранит базу данных имен устройств в памяти ядра,‭ ‬которая не может быть перемещена‭ ‬-‭ ‬она всегда постоянна.‭ ‬При большом количестве устройств в системе‭ ‬-‭ ‬это может стать потенциальной проблемой‭;
  • ‎‏devfs‭ ‬-‭ ‬практически не поддерживается.‭ ‬Основной маинтейнер пакета похоже не проявляет серьезной активности для развития devfs.‭ ‬В ядрах начиная с‭ ‬2.6.13‭ ‬devfs по умолчанию отключена.

sysfs

sysfs‭ – ‬виртуальная файловая система,‭ ‬экспортирующая в пространство пользователя информацию ядра о присутствующих в системе устройствах и драйверах.‭ ‬sysfs не может быть модулем,‭ ‬она всегда‭ ‬-‭ ‬часть ядра.

Существует непосредственная связь между sysfs и объектами инфраструктуры ядра.‭ ‬Всем зарегистрированным системой объектам инфраструктуры в‭ ‬/sys соответствуют свои каталоги.‭ ‬Форма дерева каталогов,‭ ‬берущего своё начало в‭ ‬/sys,‭ ‬максимально точно соответствует соотношению между объектами.‭ ‬Если каждое устройство или драйвер‭ ‬-‭ ‬каталог,‭ ‬то файлы этих каталогов‭ ‬-‭ ‬атрибуты этих объектов.‭ ‬Операции записи/чтения атрибутов объектов ядра становятся такими же доступными,‭ ‬как операции записи и чтения файлов.

sysfs родилась не на пустом месте,‭ ‬и если информация о связях объектов ядра‭ ‬-‭ ‬это,‭ ‬действительно,‭ ‬новость,‭ ‬то большую часть атрибутов устройств можно было получить и в‭ “‬старой‭” ‬/proc/sys.‭ ‬Файлы атрибутов в‭ ‬/sys,‭ ‬однако,‭ ‬существенно отличаются от файлов procfs,‭ ‬парсинг содержимого которых мог быть довольно сложным.

udev

Основные задачи udev:

  • ‎‏работать в режиме пользователя‭ (‬userspace‭);
  • ‏динамически обновлять каталог‭ ‬/dev‭;
  • ‎‏поддерживать постоянные имена для устройств‭ (‬например для динамически подключаемых и отключаемых‭);
  • ‏предоставить удобный интерфейс для получения информации‭ (‬метаинформации‭) ‬об устройстве.

udev разделен на подсистемы:

  • ‎‏namedev‭ ‬-‭ ‬отвечает за именование устройств.‭ ‬Позволяет гибко формировать правила именования устройств руководствуясь серийным номером устройства,‭ ‬номером шины устройства,‭ ‬топологией на шине и др.‭ ‬что позволяет четко привязывать конкретное устройство к конкретному имени вне зависимости от того когда оно было обнаружено.
  • libsysfs‭ ‬-‭ ‬библиотека для доступа к информации об устройстве.‭ ‬Эта информация полезна для прикладных программ.
  • ‏udev‭ ‬-‭ ‬динамическое формирование‭ ‬/dev. Используется hotplug.

Udev работает без использования значений major/minor,‭ ‬имея собственную систему связи и поиска устройств и драйверов.

D-bus

Проект D-bus‭ ‬-‭ ‬унифицированная технология межпроцессного взаимодействия‭ (‬IPC‭) ‬для прикладных программ,‭ ‬которые хотят в том числе и отслеживать добавление/удаление устройств.