Заметка была написана в связи в некоторой практической работой — и как её часть. Это во-первых. А во-вторых — в связи с тем, что проблемы автоматического общения с оборудованием возникают постоянно. И при этом — каждый раз новые. Ну неймётся разработчикам... Так что ниже — просто набор рецептов, опробованных на ограниченном материале.
Наконец, в-третьих, есть мнение, и совсем не моё, что HAL скоро отомрёт, как отмерла в своё время файловая система devfs. И на место его придёт механизм devicekit, каковой, собственно, и подкрадывается к нам в форме судьбоносного сумчатого медведя (Karmic Koala). Но заметка эта писалась для "здесь и сейчас".
Механизм udev, только что описанный в соответствующей заметке, отвечая за создание файлов устройств в соответствие с реальным оборудованием, в том числе и горячего подключения, не обеспечивает, однако, монтирования сменных накопителей. Это надо выполнять в ручном или в полуавтоматическом (с определением в файле /etc/fstab соответствующих устройств с опциями типа noauto, user и т.д.) режиме.
Однако есть и более радикальный метод настройки монтирования сменных носителей
от лица пользователя — использование механизма HAL (Hardware Abstraction Level).
В общем случае HAL предназначен для сокрытия различий в аппаратном обеспечении
от основной части ядра операционной системы и в той или иной мере используется
в самых разных ОС, от Windows до NetBSD (именно абстрагирование от аппаратуры обеспечивает быстрое и безболезненное портирование последней на самые различные платформы).
Однако здесь речь пойдёт об одной из вполне конкретных реализаций HAL — той, что прижилась в Linux’е и может быть задействована в родственных BSD-системах. Это — демон, первоначально разрабатывавшийся фирмой Red Hat (первый разработчик — Дэвид Цойтен (David
Zeuthen)), а ныне представляющий собой составную часть freedesktop.org.
На официальной
странице проекта можно найти исходные тексты программы, её зависимости,
а также некоторую документацию — не очень богатую и, разумеется, англоязычную.
Демон HAL получает информацию об аппаратном обеспечении от ядра ОС (в
Linux, например, — из sysfs) и предоставляет её прикладным программам в подходящем
для них (и, что немаловажно, одинаковом для всех платформ) формате, избавляя их
от необходимости обращаться к ядру самостоятельно.
При посредстве демона HAL осуществляется, в частности, автоматическое монтирование
сменных накопителей. Однако этим его роль не исчерпывается. В современных версиях Xorg через него получает информацию об аппаратуре (клавиатуре и мыши) X-сервер
— что делает возможным запуск Иксов без традиционного их конфигурационного
файла /etc/X11/xorg.conf.
Следует, однако, подчеркнуть, что сам по себе демон HAL никакие накопители не
монтирует, никакие устройства в X-сервере не настраивает. Он лишь определяет
наличные устройства, фиксирует их параметры и представляет их в виде,
доступном тем программам, которые будут заниматься непосредственно указанными
действиями — монтированием, управлением раскладками клавиатуры, поведением
кнопок мыши и так далее.
Вообще, просмотреть, какие устройства определяются HAL’ом, можно с помощью
команды:
$ lshal | less
Предупреждаю, вывод её будет весьма длинным (почему и целесообразно передать
его команде less). Зато внимательное его рассмотрение даст практически
исчерпывающую информацию о наличных устройствах и их параметрах, почему нам
ещё придётся к ней возвращаться. Например, так выглядит фрагмент, относящийся к
500-гигабайтному SATA-винчестеру Samsung:
...
scsi.model = 'SAMSUNG HD501LJ' (string)
udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062'
block.storage_device = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
info.product = 'SAMSUNG HD501LJ' (string)
info.udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
storage.model = 'SAMSUNG HD501LJ' (string)
storage.serial = 'SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
...
Это вывод команды в так называемом “длинном” формате, обеспечиваемом опцией -l (или –long), каковая, впрочем, используется по умолчанию. Возможны и более компактные или более удочитаемые формы вывода команды lshal. Так, данная в форме
$ lshal -s
она представит только список устройств, без подробной расшифровки:
...
storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062
...
А форма
$ lshal -t
выведёт список устройств в виде иерархически построенного дерева. Например, для того же диска это будет выглядеть так:
...
pci_8086_2921
pci_8086_2921_scsi_host_0
pci_8086_2921_scsi_host_0_scsi_host
pci_8086_2921_scsi_host_0_scsi_device_lun0
storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062
volume_uuid_69458f4c_c6d5_4102_a5ea_083593dbc811
volume_uuid_eb0b9b6c_8102_4704_b254_389cf8d44b92
volume_uuid_41ad983d_e238_4c51_8555_355b45ce10af
volume_uuid_56b2dede_e113_425a_9f50_c1017f9e9113
...
Посредством lshal с опцией -u можно вытащить сведения о некоем конкретном устройстве. Для чего нужно только знать его UDI (Unique Device Identifier — уникальный идентификатор устройства в системе именования HAL — это не то же самое, о чем говорилось в
предыдущей заметке), который задаётся в качестве значения этой опции. Например, команда
lshal -u storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062
даст нам полные сведения всё о том же винчестере:
udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062'
block.device = '/dev/sdb' (string)
block.is_volume = false (bool)
block.major = 8 (0x8) (int)
block.minor = 16 (0x10) (int)
block.storage_device = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
info.capabilities = {'storage', 'block'} (string list)
info.category = 'storage' (string)
info.parent = '/org/freedesktop/Hal/devices/pci_8086_2921_scsi_host_0_scsi_device_lun0' (string)
info.product = 'SAMSUNG HD501LJ' (string)
info.udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
info.vendor = 'ATA' (string)
linux.hotplug_type = 3 (0x3) (int)
linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sdb' (string)
storage.automount_enabled_hint = false (bool)
storage.bus = 'pci' (string)
storage.drive_type = 'disk' (string)
storage.firmware_version = 'CR10' (string)
storage.hotpluggable = false (bool)
storage.lun = 0 (0x0) (int)
storage.media_check_enabled = false (bool)
storage.model = 'SAMSUNG HD501LJ' (string)
storage.no_partitions_hint = false (bool)
storage.originating_device = '/org/freedesktop/Hal/devices/computer' (string)
storage.partitioning_scheme = 'mbr' (string)
storage.removable = false (bool)
storage.removable.media_available = true (bool)
storage.removable.media_size = 500107862016 (0x7470c06000) (uint64)
storage.requires_eject = false (bool)
storage.serial = 'SATA_SAMSUNG_HD501LJS0MUJ1EPB12062' (string)
storage.size = 500107862016 (0x7470c06000) (uint64)
storage.vendor = 'ATA' (string)
в относительно читаемом виде.
“Посредничество” между демоном HAL и программами, использующими полученную
от него информацию, выполняется специальными конфигурационными файлами
— именно с помощью них можно переопределить параметры устройств и условия их
использования. Это, во-первых, файл /etc/PolicyKit/PolicyKit.conf, определяющий глобальную “политику” демона, во-вторых — набор fdi-файлов для конкретных устройств,
расположенных обычно в каталоге /etc/hal/fdi/policy. Следует отметить, что в
свежеустановленном дистрибутиве последний может быть практически пуст, однако образцы этих файлов, описывающие умолчания системы, можно найти в каталоге /usr/share/hal/fdi/policy/.