2009-06-17
Заметка была написана в связи в некоторой практической работой — и как её часть. Это во-первых. А во-вторых — в связи с тем, что проблемы автоматического общения с оборудованием возникают постоянно. И при этом — каждый раз новые. Ну неймётся разработчикам... Так что ниже — просто набор рецептов, опробованных на ограниченном материале.
Наконец, в-третьих, есть мнение, и совсем не моё, что 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выведёт список устройств в виде иерархически построенного дерева. Например, для того же диска это будет выглядеть так:
...Посредством lshal с опцией -u можно вытащить сведения о некоем конкретном устройстве. Для чего нужно только знать его UDI (Unique Device Identifier — уникальный идентификатор устройства в системе именования HAL — это не то же самое, о чем говорилось в предыдущей заметке), который задаётся в качестве значения этой опции. Например, команда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 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/.