28

Кстати, что именно не так с кучей статических файлов в /dev? Очевидно, что для разработчиков недостаточно того, чтобы заново изобретать это колесо по моим подсчетам 3 раза (devfs -> udev + HAL -> udev), и теперь, по-видимому, оно также входит в программу Grand Unified Init, поэтому четыре раза.

Помню, когда я впервые начал использовать Linux много лет назад, я был удивлен, что, несмотря на заявления о том, что "все является файлом", нет /dev/eth0 (что позже имело смысл, поскольку это не символ или блочное устройство, хотя и… » пакет "тип устройства" был бы интересен ...). Учитывая это, почему программа, которая обрабатывает дерево файлов char и block device, также отвечает за сетевые устройства? Я видел смутные ссылки на "гибкость", но что это добавляет к тому, что, скажем, ifconfig (8) делает, просто просматривая /proc/net/dev? Я знаю, например, что NetworkManager не будет в сети или в OpenBSD в ближайшее время, потому что это зависит от udev , который ни одна из команд не хочет писать; я не понимаю, почему программа, которая хотя бы номинально существует для управления деревом /dev является, по-видимому, единственным способом выставить сетевые устройства , которые уже доступны множеству способов ядром (и ни одна из них в /dev !) ,

Это только из-за горячего подключения? Были ли проблемы с ядром, просто слушающим физические шины и загружающим соответствующие модули в сообщении "устройство добавлено"? Или, не дай бог, настоящий администратор так поступает? Я помню, что еще в начале 2000-х мои серверы иногда инициализировали свои сетевые карты в неожиданном порядке, и я полагаю, что имеет смысл принять решение о присвоении имен в пользовательской среде (хотя в то время это было не очень сложно исправить), но это похоже на кувалду для таракана. (Или, может быть, эта проблема затрагивает сценарии использования, о которых я не думаю гораздо сложнее, чем стоечные серверы или ПК, которые мне известны.)

Итак, чтобы сформулировать мой вопрос прямо: какие проблемы на самом деле решает udev, и как devfs, HAL и / или обычный старый файл не смогли их решить? Есть ли конкретная причина, по которой все эти разные вещи (горячее подключение, общее управление устройствами, управление сетевыми устройствами, именование устройств, приоритет драйверов и т.д.) Должны быть одной программой?

2 ответа2

33

Еще две вещи: переход Linux на корпоративные и другие крупные серверы показал, что static /dev не работает. Развивающиеся технологии, как для потребителей, так и для предприятий, выставляли static /dev как шутку. [Этот ответ заполняет большую часть предыстории, не особенно то, почему devfs был заменен на udev].

Исчерпание большого и малого номера пространства

Файлы /dev идентифицируются внутри ядра по их старшим и младшим номерам. Ядро никогда не заботилось об имени (и вы могли бы, например, mv /dev/sda /dev/disk-1 и оно продолжало бы работать - хотя, конечно, программы не знали бы, где его найти).

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

Первоначально, например, Linux начинался с 8,0 с sda, 8,1 с sda1, 8,16 с sdb и т.д. Но люди продолжали добавлять все больше дисков на машины, особенно когда вы рассматривали такие вещи, как оптоволоконный канал. Так что в какой-то момент, основные номера 65–71 были добавлены для большего количества дисков. Позже мажорные номера 128–135. И все же люди продолжали хотеть больше дисков ...

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

Конечный результат можно увидеть в списке устройств Linux LANANA. Если вы посмотрите на список 2.6 (единственный, который все еще там), то используется большое количество старших номеров блоков до 200 (максимум: 255). Ясно, что цифры закончились бы.

Переход на большее число было нелегким. Это меняет ядро ABI. В зависимости от файловой системы, это меняет расположение на диске. Но, конечно, большинство из этих устройств не существовало ни в одной из систем, даже у того, на котором (например) заканчивались диски SCSI, вероятно, было много свободных вещей - вероятно, не требовался жесткий диск IBM XT, например.

С динамическим /dev дистрибутиву не нужно отправлять номера устройств. Они больше не должны быть глобально уникальными. Они даже не должны быть уникальными среди сапог.

Названия устройств были непредсказуемыми

Раньше было действительно легко присвоить номер всему. На плате было два канала IDE; каждый канал IDE поддерживает одного главного и одного подчиненного. Вы можете назначить в порядке канала и в порядке «ведущий-потом-ведомый». Таким образом, hda становится первым каналом, мастер; Первый канал hdb , раб; hdc второй канал, мастер; и т. д. Те были предсказуемы и стабильны. Они могут измениться, если вы добавите новый диск или удалите один, но при отсутствии смены оборудования, они были статическими.

Вы можете поместить /dev/hda1 в ваш /etc/fstab и быть уверенным, что он будет работать, по крайней мере, при отсутствии аппаратных изменений.

IDE работал так. Ничего после этого не делает.

SATA выглядит просто: один порт, один диск. Но не так; это позволяет множители портов. И это позволяет горячую замену. Тем не менее, при отсутствии изменений в оборудовании, вы можете по-прежнему поддерживать отображение.

USB намного хуже. Это не только позволяет горячую замену, это типично. Люди постоянно подключают USB-накопители. Кроме того, устройствам может потребоваться некоторое время для проверки - и они могут фактически меняться всякий раз, когда им это нравится (например, при включении или выключении режима USB-накопителя на вашем телефоне). Firewire похож. Ни с одним из них вы не сможете придумать стабильное отображение.

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

Стремление к скорости загрузки также ухудшило ситуацию. Первоначально ядро с удовольствием сидело бы без дела и долго ждали, например, все USB-устройства для инициализации. Чтобы полностью исследовать все шины SCSI и т.д. Эти зонды были превращены в фоновые задачи; boot больше не будет ждать их Устройства добавляются после завершения проверки.

Таким образом, ядро осталось более или менее «в любом порядке, в котором они появляются». Это означало, что многие типы устройств могут изменять порядок загрузки при каждой загрузке - то, что было в одной загрузке /dev/sdb было в другой загрузке /dev/sdc . Это делает идею статического /dev шуткой.

Резюме

Когда вы используете комбинацию static /dev становится все более бессмысленной из-за непредсказуемых порядков проверки устройств и продолжает выделять статические старшие / младшие номера, ведущие к существенной работе, которая не заканчивается, становится понятно, почему разработчики Linux решили переключиться на динамический /dev

24

Хороший вопрос.

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

Однако, принимая это за чистую монету, на ваш вопрос ответили в этой статье Википедии:

В отличие от традиционных систем Unix, где узлы устройств в каталоге /dev были статическим набором файлов, диспетчер устройств Linux udev динамически предоставляет только узлы для устройств, фактически присутствующих в системе. Хотя devfs раньше предоставлял похожую функциональность, Грег Кроа-Хартман привел ряд причин, по которым его реализация предпочтительнее, чем devfs:

1) udev поддерживает постоянное именование устройств, которое не зависит, например, от порядка, в котором устройства подключены к системе. Настройка udev по умолчанию предоставляет постоянные имена для устройств хранения. Любой жесткий диск распознается по уникальному идентификатору файловой системы, имени диска и физическому расположению на оборудовании, к которому он подключен.

2) udev выполняется полностью в пространстве пользователя, а не в пространстве ядра devfs. Одним из следствий этого является то, что udev переместил политику именования из ядра и может запускать произвольные программы для составления имени для устройства из свойств устройства до создания узла; там весь процесс также прерывается, и он работает с более низким приоритетом.

Я, вероятно, должен добавить, что с udev исключается возможность состояния race condition , которое в основном подрывает именование устройств в devfs и hotplug. Другими словами: с devfs не было никакого способа гарантировать, что ваш самый левый порт Ethernet будет называться eth0 а его самый правый - eth1 , что делает (в качестве чистого примера) настройку маршрутизаторов (один порт для WAN, один порт для LAN) сложно реализовать.

Принятие схемы именования дисков, основанной на GUID, является еще одним плюсом и переводит весь процесс в пользовательское пространство еще более масштабным: вы просматривали этот сайт, чтобы увидеть, сколько людей пишут свои собственные правила udev?

В качестве простого примера преимуществ, присущих наличию udev в пользовательском пространстве, проверьте либо этот вопрос, либо этот другой вопрос, оба на этом самом сайте.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .