Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Linux From Scratch (version 6.8)
Назад Глава 7. Настройка скриптов загрузки системы Вперед

7.9. Управление устройствами и модулями в системе LFS

В главе 6 мы установили пакет Udev. Прежде чем вдаваться в подробности относительно того, как он работает, кратко опишем предшествующие способы работы с устройствами в порядке их появления.

В системе Linux традиционно используется статический метод создания устройств, при этом очень много нодов устройств создается в директории /dev (иногда в буквальном смысле тысячи нодов) вне зависимости от того, существуют ли в действительности соответствующие аппаратные устройства. Обычно это делается с помощью скрипта MAKEDEV, в котором выполняется ряд вызовов программы mknod с соответствующими указанием максимальных и минимальных номеров для различных устройств, которые могут вообще существовать.

Когда используется подход Udev, ноды устройств создаются только для тех устройств, которые обнаруживаются ядром. Поскольку ноды этих устройств должны создаваться каждый раз во время загрузке системы, они будут запоминаться в файловой системе tmpfs (виртуальная файловая система, которая полностью располагается в оперативной памяти). Для нодов устройств много места не нужно, поэтому размер занимаемой памяти несущественен.

7.9.1. Историческая справка

В феврале 2000 года в ядро 2.3.46 была добавлена новая файловая система, которая называлась devfs, и она присутствовала в стабильных ядрах серии 2.4. Хотя метод динамического создания устройств был в самом исходном коде ядра, он у основных разработчиков ядра никогда не получал достаточной поддержки.

Основная проблема в подходе, используемом с devfs, была связана с тем, как устройства обнаруживались и создавались и как им назначались имена. Последняя проблема, связанная с назначением имен, была, пожалуй, самой важной. Принято считать, что если имена устройств могут настраиваться, то политика именования устройств должна полностью определяться системным администратором, а не навязываться ему каким-либо конкретным разработчиком (разработчиками). Файловая система devfs также страдала от эффекта "гонок" (race condition), который связан с конструкцией файловой системы и его нельзя избежать без существенных изменений в ядре. Из-за отсутствия технической поддержки, эта файловая система в течение длительного периода времени была помечена как устаревшая (deprecated), и, наконец, в июне 2006 года она была удалена.

В процессе разработки нестабильной ветки ядра 2.5, которая затем была реализована в виде стабильных ядер серии 2.6, появилась новая виртуальная файловая система, названная sysfs. Задача файловой системы sysfs состоит в экспорте отображения аппаратной конфигурации системы в процессы пользовательского пространства. Благодаря такому представлению в пользовательском пространстве просмотр новой файловой системы стал более простым и удобным, чем просмотр devfs.

7.9.2. Реализиция Udev

7.9.2.1. Файловая система Sysfs

Файловая система sysfs кратко была описана выше. Можно спросить о том, откуда файловая система sysfs узнает об устройствах, имеющихся в системе, и какие для устройств должны использоваться номера. Как только ядро обнаруживает соответствующие объекты, драйверы, скомпилированные вместе с ядром, непосредственно регистрируют эти объекты в системе sysfs. Регистрация с помощью драйверов, скомпилированных в виде модулей, выполняется сразу, как только соответствующие модули будут загружены. Сразу, как только файловая система sysfs будет смонтирована (в /sys), информация, зарегистрированная встроенными драйверами в sysfs, становится доступной процессам пользовательского пространства и процессу udevd, создающему ноды устройств.

7.9.2.2. Скрипт загрузки Udev

Скрипт начальной загрузки S10udev ответственен за создание нодов устройств во время загрузки Linux. Скрипт отключает обработчик событий uevent, которым по умолчанию является /sbin/hotplug. Это делается потому, что ядру больше не требуется обращаться к внешнему исполняемому модулю. Вместо этого udevd будет слушать по сетевому сокету, открытому ядром, события uevents. Затем загрузочный скрипт копирует все статические ноды устройств, которые есть в директории /lib/udev/devices, в директорий /dev. Это необходимо, поскольку некоторые устройства, директории и символические ссылки уже необходимы на ранних этапах загрузки системы перед запуском процессов динамической обработки устройств, а также нужны самому процессу udevd. Создание статических нодов устройств в директории /lib/udev/devices также позволит иметь дело с устройствами, работа с которыми не поддерживается инфраструктурой динамической обработки устройств. Затем загрузочный скрипт запускает демон udevd, который будет обрабатывать каждое событие uevent, которое он получит. Наконец, загрузочный скрипт заставит ядро повторно выдать событие uevents для каждого устройства, которые было зарегистрировано, а затем ожидает, пока udevd их обработает.

7.9.2.3.Создание нодов устройств

Чтобы получить правильный максимальный и минимальный номер устройства, Udev использует информацию, имеющуюся в sysfs в директории /sys. Например, в файле /sys/class/tty/vcs/dev имется строка "7:0". Эта строка используется udevd для создания нода устройства с максимальным номером 7 и минимальным номером 0. Имена и права доступа к нодам, создаваемым в директории /dev, определяются по правилам, указанным в файлах, находящимся в директории /etc/udev/rules.d/. Нумерация аналогично той, что используется в пакете LFS-Bootscripts. Если udevd не может найти правило для устройства, он создает его с правами доступа 660 и правами доступа root:root. Документация по синтаксису конфигурационных файлов для правил Udev имеется в файле /usr/share/doc/udev-166/writing_udev_rules/index.html.

7.9.2.4. Загрузка модулей

Драйверы устройств, скомпилированые в виде модулей, могут содержать алиасы. Алиасы можно увидеть в данных, выдаваемых modinfo; о них обычно говорят как об идентификаторах конкретных шин для устройства, работа с которыми поддерживается модулем. Например, в драйвере snd-fm801, в который поддерживается работа устройств PCI с идентификатором производителя 0x1319 и идентификатором устройства ID 0x0801, есть алиас "pci:v00001319d00000801sv*sd*bc04sc01i*". Для большинства устройств алиас драйвера, который должен работать с устройством, экспортируется драйвером шины через файловую систему sysfs. Например, в файле /sys/bus/pci/devices/0000:00:0d.0/modalias может быть строка "pci:v00001319d00000801sv00001319sd00001319bc04sc01i00". В правилах, используемых Udev по умолчанию определено, что udevd должен вызвать /sbin/modprobe со значением, находящимся в перееменной среды окружения MODALIAS (которое должно совпадать с содержимым файла modalias в файловой системе sysfs), осуществляя, тем самым, загрузку всех модулей, алиасы в которых после выполнения в этой строке всех подстановок совпадают с содержимым этой строки.

В данном примере это означает, что, кроме драйвера snd-fm801, будет загружен устаревший (и ненужный) драйвер forte, если он доступен. Далее описаны способы, предотвращающие загрузку ненужных драйверов.

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

7.9.2.5. Управление устройствами с горячим подключением / динамическими устройствами

Когда вы подключаете устройство, например, MP3-плеер к шине Universal Serial Bus (USB), ядро распознает, какое устройство подключено, и создает событие uevent. Затем событие uevent будет обработано так, как это описано выше.

7.9.3. Проблемы с загрузкой модулей и созданием устройств

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

7.9.3.1. Модуль ядра не загружается автоматически

Udev будет загружать модуль только, если в нем указан алиас для конкретной шины и драйвер шины должным образом экспортирует нужные алиасы в файловую систему sysfs. В остальных случаях загрузка модулей должна осуществляться иначе. Известно, что для Linux-2.6.37 с помощью Udev загружаются правильно написанные драйверы для устройств INPUT, IDE, PCI, USB, SCSI, SERIO и FireWire.

Чтобы определить, есть ли в Udev поддержка драйвера необходимого вам устройства, запустите modinfo с именем модуля в качестве аргумента. Затем найдите в /sys/bus директорий для этого устройства и проверьте, есть ли в нем файл modalias.

Если файл modalias есть в sysfs, то драйвер поддерживает работу с устройством и его можно вызывать непосредственно, но в нем нет алиаса, что является ошибкой драйвера. Загружайте драйвер без использования Udev и ждите, пока позже эта проблема будет решена.

Если в соответствующем директории в /sys/bus файл modalias отсутствует, то это значит, что разработчики ядра еще не добавили поддержку modalias для шины этого типа. Для Linux-2.6.37 это касается шин ISA. Подождите, пока в более поздних версиях ядра эта проблема будет решена.

Udev вообще не предназначен для загрузки драйверов - "оберток", например, snd-pcm-oss, и драйверов, не предназначенных для работы с устройствами, например, loop.

7.9.3.2. Модуль ядра не загружается автоматически и Udev не пытается загрузить его

Если модуль-"обертка" только расширяет функциональные возможности, предоставляемые некоторым другим модулем (например, snd-pcm-oss расширяет функции snd-pcm, позволяя приложениям OSS получать доступ к звуковым картам), то настройте modprobe так, чтобы он загружал модуль -"обертку" после того, как Udev загрузит модуль, находящийся внутри обвертки. Чтобы это сделать, добавьте строку "install" ("установить") в файл вида /etc/modprobe.d/<имяфайла>.conf. Например:

install snd-pcm /sbin/modprobe -i snd-pcm ; \
    /sbin/modprobe snd-pcm-oss ; true

Если рассматриваемый модуль не является оберткой и используется самостоятельно, то сконфигурируйте загрузочный скрипт S05modules так, чтобы он загружал этот модуль во время загрузки системы. Чтобы сделать это, добавьте имя модуля отдельной строкой в /etc/sysconfig/modules. Этот метод можно также использовать для модулей -"оберток", но такой подход не очень оптимален.

7.9.3.3. Udev загружает не тот модуль

Либо этот модуль не собран, либо этот модуль помещен в черный список в файле /etc/modprobe.d/blacklist.conf так, как это сделано с модулем forte в примере, приведенном ниже:

blacklist forte

Модули, указанные в черном списке, можно загрузить вручную с помощью явно указываемой команды modprobe.

7.9.3.4. Udev создает неправильное устройство или неверную символическую ссылку

Это обычно происходит в случае, когда правило применяется к случайно найденному устройству. Например, плохо написанное правило может быть применимо как к диску SCSI (как это и требуется), так и к соответствующему обобщенному устройству SCSI (что неправильно), поставляемому производителем. С помощью команды udevadm info найдите неверно написанное правило и сделайте его более конкретным.

7.9.3.5. Правило Udev работает ненадежно

Это может быть еще одним проявлением предыдущей проблемы. Если это не так и в вашем правиле используются атрибуты sysfs, то проблема может быть связана с временными задержками в ядре и такое ядро следует позже пропатчить. Ну а сейчас вы можете обойти эту проблему, создав правило, которое будет ожидать, пока можно будет использовать атрибут sysfs, и добавить это правило в файл /etc/udev/rules.d/10-wait_for_sysfs.rules (создайте этот файл, если он не существует). Пожалуйста, сообщите об этом в списке разработки системы LFS (LFS Development list), вы этим окажете нам помощь.

7.9.3.6. Udev не создает устройство

Далее в тексте предполагается, что драйвер статически встроен в ядро или уже загружен как модуль, и что вы уже проверили, что Udev не создает устройства с неправильным именем.

В Udev не будет информации, необходимой для создания нода устройства, если драйвер ядра не будет экспортировать свои данные в sysfs. Это наиболее распространенная ситуация, связанная с драйверами, не входящими в дерево ядра и разрабатываемыми третьей стороной. Создайте в /lib/udev/devices статический нод устройства с соответствующими максимальным и минимальным номерами (смотрите в документации по ядру файл devices.txt или документацию, представляемую поставщиком, разработавшим драйвер). Статический нод устройства будет скопирован в /dev загрузочным скриптом S10udev.

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

Это связано с тем, что Udev, в соответствие со своей организацией, обрабатывает события uevents и загружает модули параллельно, и, следовательно, в произвольном порядке. Этот порядок никогда не удастся "зафиксировать". Вы не должны полагаться на то, что имена устройств, создаваемые ядром, всегда будут стабильными. Вместо этого, создайте свои собственные правила, в которых будут создаваться символические ссылки со стабильными именами; используйте для этого некоторые устойчивые признаки устройств, такие как серийные номера или значения вида *_id, выдаваемые некоторыми утилитами, установленными с помощью Udev. Смотрите примеры в разделе 7.10 "Создание пользовательских символических ссылок на устройства" и в разделе 7.13 "Конфигурирование скрипта network".

7.9.4. Дополнительный материал

Дополнительную полезную документацию можно получить на следующих сайтах:


Предыдущий раздел: Оглавление Следующий раздел:
Файлы запуска командной оболочки Bash   Создание пользовательских символических ссылок на устройства