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
 
 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/sdaist sog. top-level device path
-  Verzeichnis, welches den Eintrag deventhält (Major-/Minornumber)
 
  
    
      |  | 
$ 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/sysdes Gerätes, beginnend mit "/devices/"
-  ggf. weitere, z.B. DEVICEbei USB-Geräten, enthält entsprechenden Eintrag im USB-FS (/proc/bus/usb/...)
 
 
-  /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/)
 
 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.rulesenthä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 usbangeschlossen ist (genauer: im devpath zum Gerät muss das Subsystemusbliegen)
-  dann wird der symbolische Link /dev/usbdisk%neingerichtet
-  %nist die kernel number des Geräts (die3aus/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
 
-  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'
 
 
-  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-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