Device Handling im Linux
Vorgeschichte
- Unix: Alles ist ein File
- Device-Files (
/dev/tty0
) ermöglichen Zugang zu Geräten (Major-/Minor-Number) - Devices-Files entstehen durch
mknod
- Devices-Files existieren unabhängig vom Gerät
- Ansatz ist unflexibel/fehleranfällig
- mehrere Ansätze zur dynamischen Erkennung von Geräten (Dev-FS, udev)
- Ziele:
- Device-Files erzeugen/entfernen nach Bedarf
- Regeln entscheiden über die Namen der Device-Files (nicht die Reihenfolge, in der die Geräte erkannt werden)
- Geräte in grafische Desktops einbinden (z.B. Applikationen starten)
- Zugriffsberechtigungen setzen
- Filesysteme montieren/demontieren
- Stand
- große Unterschiede zwischen
- Kernel-Versionen
- Distributionen
- Schwerpunkt: aktuelle, moderne Verfahren
- Erläuterungen am Beispiel von Scientific Linux 5.0 / Fedora Core 6
- große Unterschiede zwischen
Controller / Kernel / Gerätetreiber
- Controller des jeweiligen Busses (ISA, USB, PCI)
- erzeugt Interrupt bei Anschluss oder Entfernen eines Gerätes
- Interrupt-Behandlung:
- Informationen über das Gerät ermitteln
- Controller "befragen"
- Konfig-Bereich von PCI-Karten auslesen (Vendor/Product-ID)
- Verwaltungsinformationen ablegen (Kobject)
- sysfs-Eintrag erzeugen
- Ereignis an Anwendungen weiterleiten (uevent)
Sysfs
- virtuelles Filesystem
- exportiert Informationen zu Geräten aus dem Kernel in Userspace
- beginnt in
/sys
- für jedes Gerät und jeden Treiber existiert ein Verzeichnis in
/sys
- Eltern-Kind-Beziehungen werden durch Unterzeichnisse reflektiert
- ein Gerät an einem Bus
- eine Partition auf einer Festplatte
- verschiedene Pfade ermöglichen den Zugang zu Informationen aus verschiedenen Perspektiven
- intensiver Gebrauch von symb. Links
/sys/devices/
Device Tree, physische Sicht /sys/bus/
Zuordnung der Geräte zu den einzelnen Bussen /sys/class/
Zuordnung der Geräte zu Geräteklassen
- Beispiel: interne SATA-Festplatte
sda
![]() |
/sys/devices/pci0000:00/0000:00:0e.0/host0/target0:0:0/0:0:0:0/ /sys/bus/scsi/devices/0:0:0:0 /sys/class/scsi_disk/0:0:0:0 /sys/class/scsi_device/0:0:0:0 /sys/class/scsi_generic/sg0 /sys/block/sda |
-
/sys/block/sda
ist sog. top-level device path- Verzeichnis, welches den Eintrag
dev
enthält (Major-/Minornumber)
- Verzeichnis, welches den Eintrag
![]() |
$ find /sys -name dev |grep sda /sys/block/sda/sda2/dev /sys/block/sda/sda1/dev /sys/block/sda/dev $ cat /sys/block/sda/dev 8:0 |
udev
- Hotplug-Verfahren des Linux-Gerätemanagements
- Erzeugen der Einträge in
/dev/
im Userspace - Ziele/Möglichkeiten:
- default names umbennen
- alternative/persistene Namen für Geräte in Form eines symb. Links zum default name erzeugen
- Name durch externes Programm ermitteln lassen
- Eigentümer/Gruppe und Zugriffsberechtigungen setzen
- Script beim Hinzufügen und/oder Entfernen eines Gerätes starten
- befolgt konfigurierbare Namenskonventionen
- bearbeitet uevents
- Geräteklasse als Argument: z.B.
usb
,scsi
,net
,ieee1394
, ... - weitere Informationen in Umgebungsvariablen
-
ACTION
:add
|remove
[ |mount
|umount
] -
SEQNUM
: Folgenummer, definiert Reihenfolge der uevents -
DEVPATH
: Pfad in/sys
des Gerätes, beginnend mit "/devices/" - ggf. weitere, z.B.
DEVICE
bei USB-Geräten, enthält entsprechenden Eintrag im USB-FS (/proc/bus/usb/...
)
-
- Geräteklasse als Argument: z.B.
-
/sbin/udevd
- serialisiert uevents anhand der
SEQNUM
- verzögert uevents für child devices (z.B. USB-Stick) bis handling des parent device (z.B. USB-Controller) beendet ist
- behandelt uevents in Kind-Prozessen
- konfiguriert über
/etc/udev/udev.conf
- definiert allgemeingültige Einstellungen
-
udev_root
: device directory (/dev
) -
udev_rules
: udev rules file or directory (/etc/udev/rules.d
) -
udev_log
: logging priority (err
)
- führt Aktionen entsprechend zutreffender Regeln aus
- führt Hilfsprogramme aus (
/lib/udev/
)
- serialisiert uevents anhand der
Persistente Namen
- "built-in"-Schema für Storage Devices in
/dev/disk/
![]() |
$ ls -lR /dev/disk /dev/disk: insgesamt 0 drwxr-xr-x 2 root root 160 16. Mär 13:33 by-id drwxr-xr-x 2 root root 180 16. Mär 13:33 by-path drwxr-xr-x 2 root root 100 16. Mär 13:33 by-uuid /dev/disk/by-id: insgesamt 0 lrwxrwxrwx 1 root root 9 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1551209 -> ../../sda lrwxrwxrwx 1 root root 10 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1551209-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1551209-part2 -> ../../sda2 lrwxrwxrwx 1 root root 9 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1570429 -> ../../sdb lrwxrwxrwx 1 root root 10 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1570429-part1 -> ../../sdb1 lrwxrwxrwx 1 root root 10 16. Mär 13:33 scsi-SATA_WDC_WD2500YS-01_WD-WCANY1570429-part2 -> ../../sdb2 /dev/disk/by-path: insgesamt 0 lrwxrwxrwx 1 root root 9 16. Mär 13:33 pci-0000:00:0d.0-ide-0:0 -> ../../hda lrwxrwxrwx 1 root root 9 16. Mär 13:33 pci-0000:00:0e.0-scsi-0:0:0:0 -> ../../sda lrwxrwxrwx 1 root root 10 16. Mär 13:33 pci-0000:00:0e.0-scsi-0:0:0:0-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 16. Mär 13:33 pci-0000:00:0e.0-scsi-0:0:0:0-part2 -> ../../sda2 lrwxrwxrwx 1 root root 9 16. Mär 13:33 pci-0000:00:0e.0-scsi-1:0:0:0 -> ../../sdb lrwxrwxrwx 1 root root 10 16. Mär 13:33 pci-0000:00:0e.0-scsi-1:0:0:0-part1 -> ../../sdb1 lrwxrwxrwx 1 root root 10 16. Mär 13:33 pci-0000:00:0e.0-scsi-1:0:0:0-part2 -> ../../sdb2 /dev/disk/by-uuid: insgesamt 0 lrwxrwxrwx 1 root root 10 16. Mär 13:33 23cb3db6-36c3-bcd6-3f69-3d1c8639bfb8 -> ../../sda2 lrwxrwxrwx 1 root root 9 16. Mär 13:33 27f0c8b9-a496-4234-8716-187918fd46be -> ../../md0 lrwxrwxrwx 1 root root 10 16. Mär 13:33 e5b48c8a-833a-40a5-65d0-716cf26601c0 -> ../../sda1 |
udev-Regeln
-
/etc/udev/rules.d/*.rules
- Files mit Regeldefinitionen zur Namensbildung
- einzelne Files dienen der Gruppierung von Regeln
- Sortierreihenfolge der Filenamen!
![]() |
$ ls /etc/udev/rules.d 05-udev-early.rules 55-usbdisk.rules 60-wacom.rules bluetooth.rules 20-scanner.rules 60-libsane.rules 90-alsa.rules xen-backend.rules 50-udev.rules 60-net.rules 90-hal.rules 51-hotplug.rules 60-pcmcia.rules 95-pam-console.rules |
- Beachte:
/etc/udev/rules.d/50-udev.rules
enthält sog. default-Regeln, daran nichts ändern! - eine Zeile definiert das Mapping von Geräteeigenschaften (device attributes) und Gerätename (device name)
- pro Zeile wenigstens ein key value pair, es können mehrere keys definiert werden (getrennt durch Komma)
- zwei Arten von keys
- match keys
- assignment keys
- entspricht das aktuelle Gerät allen match keys wird die Regel angewendet und der definierte Name wird verwendet
- es werden alle zutreffenden Regeln angewendet (aus allen Regel-Files)
- mehrere (unabhängige) Namen für ein Gerät möglich
- kommt kein Treffer zustande wird der kernel device name (default name) vergeben
Beispiele
![]() |
$ cat /etc/udev/rules.d/55-usbdisk.rules # usb disk KERNEL=="sd[a-z]*", BUS=="usb", SYMLINK="usbdisk%n" |
- wenn der default Name auf das Muster
sd[a-z]*
passt und - wenn das Gerät am Bus
usb
angeschlossen ist (genauer: im devpath zum Gerät muss das Subsystemusb
liegen) - dann wird der symbolische Link
/dev/usbdisk%n
eingerichtet-
%n
ist die kernel number des Geräts (die3
aus/dev/sda3
)
-
- Beachte: das ist fehleranfällig: Was passiert wenn mehrere USB-Disks, -Sticks angeschlossen werden?
![]() |
$ cat !$ cat 90-hal.rules # pass all events to the HAL daemon RUN+="socket:/org/freedesktop/hal/udev_event" |
- nur assignment key
- weiterleiten des uevents an HAL
![]() |
$ cat 40-multipath.rules # multipath wants the devmaps presented as meaninglful device names # so name them after their devmap name SUBSYSTEM!="block", GOTO="end_mpath" KERNEL!="dm-[0-9]*", ACTION=="add", PROGRAM=="/bin/bash -c '/sbin/lsmod | /bin/grep ^dm_multipath'", RUN+="/sbin/multipath -v0 %M:%m" KERNEL!="dm-[0-9]*", GOTO="end_mpath" ACTION=="add", RUN+="/sbin/dmsetup ls --target multipath --exec '/sbin/kpartx -a' -j %M -m %m" PROGRAM=="/sbin/dmsetup ls --target multipath --exec /bin/basename -j %M -m %m", RESULT=="?*", NAME="%k", SYMLINK="mpath/%c" PROGRAM!="/bin/bash -c '/sbin/dmsetup info -c --noheadings -j %M -m %m | /bin/grep -q .*:.*:.*:.*:.*:.*:.*:part[0-9]*-mpath-'", GOTO="end_mpath" PROGRAM=="/sbin/dmsetup ls --target linear --exec /bin/basename -j %M -m %m", NAME="%k", RESULT=="?*", SYMLINK="mpath/%c" LABEL="end_mpath" $ grep "dm-" 50-udev.rules KERNEL=="dm-[0-9]*", OPTIONS+="ignore_device" |
- Behandlung von multipath devices
- andere device mapper nodes sollen von udev ignoriert werden
Zusammenfassung
- zahlreiche Möglichkeiten
- oftmals mehrere match keys erforderlich, um ein Gerät genau zu identifizieren
- siehe Manual zu
udev(7)
und Writing udev rules - udev erzeugt immer nur einen device node, weitere Namen als symb. Links
- als device node wird i.d.R. der default name benutzt
- Experimentieren mit:
-
udevmonitor
-
udevinfo
-
udevtest
-
HAL / D-BUS
- HAL: Hardware Abstraction Layer
- einheitliche Darstellung der vorhandenen Hardware
- Hardware-Komponenten werden als device object dargestellt
- unique identifier
- z.B.:
/org/freedesktop/Hal/devices/storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209
- z.B.:
- device properties (key-value pairs)
- abgeleitet aus der Komponente und ihrer Konfiguration selbst
- aus sog. device information files (
*.fdi
) - z.B.:
block.device = '/dev/sda'
- unique identifier
- benutzt/unterstützt D-BUS
- IPC-Framework
- Protokoll zum
- asynchronen Nachrichtenaustausch über einen daemon oder
- direkten Nachrichtenaustausch zwischen peers
- zwei daemon-Prozesse
-
dbus-daemon --system
-
/etc/rc.d/init.d/messagebus
- systemweite Nachrichten (hinzukommen/entfernen von Geräten)
-
-
dbus-daemon --session
- gestartet bei Login über grafischem Desktop
- IPC-Mechanismus von Applikationen des Desktops (GNOME, KDE)
-
- Anwendungen registrieren ihr Interesse an bestimmten Ereignissen
- plug-and-play-Mechanismus für Desktops
Architektur
Zusammenwirken von D-Bus, HAL, udev:
HAL-Architekturschema:
- HAL daemon
- verwaltet Datenbasis aller HW-Komponenten (device object list)
- stellt Informationen zusammen (
*.fdi
, ...) - erkennt und beobachtet Busse (PCI, USB) und Geräte (network, storage)
- aktiviert externe Programme (callouts) um Änderungen an system _level components durchzuführen (z.B. Modifikation von
/etc/fstab
) - sendet Nachrichten über D-Bus an session level components
- Applikationen
- benutzen HAL zur Informationsgewinnung über Geräte (z.B. Device Node)
- Grafische Desktops (GNOME, KDE) benutzen einen session level daemon um policies umzusetzen
- montieren des Filesystems auf einem USB-Stick, ...
- Start einer Foto-Management-Anwendung bei Anschluss einer Kamera
- ...
Komponenten
- vollständige Liste:
rpm -ql hal
/usr/sbin/hald | HAL daemon |
/etc/rc.d/init.d/haldaemon | Start-Script |
/usr/bin/lshal | Anzeige der HAL device objects |
/usr/bin/hal-device-manager | GUI zur Anzeige der HAL device objects |
/usr/bin/hal-{get,set}-property | Einzelne Eigenschaften abfragen/setzen |
/usr/libexec/hald* | Hilfsprogramme |
/usr/share/hal/fdi/ | Repository der device information files |
/usr/lib/libhal.so | HAL API |
/usr/lib/libhal_storage.so | HAL API für storage devices |
Applikationen
- die folgenden Anwendungen benutzen die HAL API, die Liste ist nicht vollständig ...
eggcups evolution gfloppy gnome-cd gnome-default-printer gnome-eject gnome-mount gnome-power-manager gnome-power-preferences gnome-sound-properties gnome-umount gnome-volume-manager gnome-volume-properties gswitchit-plugins-capplet hal-device hal-find-by-capability hal-find-by-property hal-get-property hal-set-property lshal nautilus-cd-burner nm-applet nm-tool rhythmbox sound-juicer totem
Datenbasis
![]() |
$ $ lshal -l -u storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209 udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209' volume.ignore = true (bool) block.storage_device = '/org/freedesktop/Hal/devices/storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209' (string) info.udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209' (string) storage.partitioning_scheme = 'mbr' (string) storage.removable.media_size = 250999111168 (0x3a70b67e00) (uint64) storage.requires_eject = false (bool) storage.hotpluggable = false (bool) info.capabilities = {'storage', 'block'} (string list) info.category = 'storage' (string) info.product = 'WDC WD2500YS-01S' (string) info.vendor = 'ATA' (string) storage.size = 250999111168 (0x3a70b67e00) (uint64) storage.removable = false (bool) storage.removable.media_available = true (bool) storage.physical_device = '/org/freedesktop/Hal/devices/pci_10de_266_scsi_host_0_scsi_device_lun0' (string) storage.lun = 0 (0x0) (int) storage.firmware_version = '20.0' (string) storage.serial = 'SATA_WDC_WD2500YS-01_WD-WCANY1551209' (string) storage.vendor = 'ATA' (string) storage.model = 'WDC WD2500YS-01S' (string) storage.drive_type = 'disk' (string) storage.automount_enabled_hint = true (bool) storage.media_check_enabled = false (bool) storage.no_partitions_hint = false (bool) storage.bus = 'scsi' (string) block.is_volume = false (bool) block.minor = 0 (0x0) (int) block.major = 8 (0x8) (int) block.device = '/dev/sda' (string) linux.hotplug_type = 3 (0x3) (int) info.parent = '/org/freedesktop/Hal/devices/pci_10de_266_scsi_host_0_scsi_device_lun0' (string) linux.sysfs_path_device = '/sys/block/sda' (string) linux.sysfs_path = '/sys/block/sda' (string) $ hal-get-property --udi /org/freedesktop/Hal/devices/storage_serial_SATA_WDC_WD2500YS_01_WD_WCANY1551209 --key block.device /dev/sda $ hal-device-manager |
Verweise
- http://kernel.org/pub/linux/utils/kernel/hotplug/udev.html
- http://www.freedesktop.org/wiki/Software/dbus
- http://www.freedesktop.org/Software/hal
- HAL 0.5.8 Specification
- KDE Wiki : DBUS
- Oliver Frommel:
Flotte Verkehrsmittel - Interprozesskommunikation mit B-BUS und Hall
Linux-Magazin 05/2006 - Raus. Rein. Passt!
Titel-Thema in Linux-Magazin 09/2006 - http://wiki.rdiff-backup.org/wiki/index.php/USBBackupScript