Udev

Aus Siduction Wiki DE
Wechseln zu: Navigation, Suche

Was ist udev?

Früher gab es das starre Anlegen von Geräten per "devfs". Dies führte zu zum Teil riesigen Verzeichnissen unterhalb /dev. Mit udev werden die Geräte zur Laufzeit dynamisch angelegt, wobei udev Events in sysfs per libsysfs auswertet. libsysfs ist eine Schnittstelle auf das vom Kernel bereitgestellte virtuelle Dateisystem "sysfs". Durch sysfs exportiert der Kernel Informationen über seine Strukturen in den Userspace (in Form von Ordnern, Dateien und Links unterhalb /sys).

Wird nun ein Gerät angesteckt, z.B. ein USB-Stick, so kann man sysfs bei der Arbeit zuschauen, indem man vorher "udevadm monitor" eingibt. Darauf erfolgt eine Ausgabe ähnlich dieser:

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[1289555947.028945] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5 (usb)
KERNEL[1289555947.029989] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0 (usb)
KERNEL[1289555947.030047] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/usb_device/usbdev2.3 (usb_device)
UDEV  [1289555947.034103] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5 (usb)
UDEV  [1289555947.042039] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/usb_device/usbdev2.3 (usb_device)
KERNEL[1289555947.072987] add      /module/usb_storage (module)
UDEV  [1289555947.073263] add      /module/usb_storage (module)
KERNEL[1289555947.073300] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8 (scsi)
KERNEL[1289555947.073336] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/scsi_host/host8 (scsi_host)
KERNEL[1289555947.073391] add      /bus/usb/drivers/usb-storage (drivers)
UDEV  [1289555947.073585] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0 (usb)
UDEV  [1289555947.073598] add      /bus/usb/drivers/usb-storage (drivers)
UDEV  [1289555947.073658] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8 (scsi)
UDEV  [1289555947.074976] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/scsi_host/host8 (scsi_host)
KERNEL[1289555948.075594] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0 (scsi)
KERNEL[1289555948.075784] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0 (scsi)
KERNEL[1289555948.076006] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/scsi_disk   /8:0:0:0 (scsi_disk)
UDEV  [1289555948.076048] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0 (scsi)
KERNEL[1289555948.076758] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/scsi_device  /8:0:0:0 (scsi_device)
KERNEL[1289555948.076997] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0 /scsi_generic/sg2 (scsi_generic)
KERNEL[1289555948.077201] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/bsg/8:0:0:0 (bsg)
KERNEL[1289555948.080012] change   /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0 (scsi)
UDEV  [1289555948.081673] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0 (scsi)
UDEV  [1289555948.087956] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0 (scsi_disk)
UDEV  [1289555948.088010] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/scsi_device/8:0:0:0 (scsi_device)
UDEV  [1289555948.088053] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/bsg/8:0:0:0 (bsg)
UDEV  [1289555948.088093] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [1289555948.088514] change   /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0 (scsi)
KERNEL[1289555948.259968] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/block/sdb (block)
KERNEL[1289555948.260032] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/block/sdb/sdb1 (block)
KERNEL[1289555948.260064] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [1289555948.260994] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [1289555948.314916] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/block/sdb   (block)
UDEV  [1289555948.349769] add      /devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/block/sdb/sdb1 (block)

Hier wird also dem Gerät eine Adresse vergeben und man sieht: das Gerät hängt am PCI-Bus 0 und ist ein USB2 Gerät unter /sdb/ mit der Partition /sdb1. Hier tritt nun "udev" in Aktion und legt eine Gerätedatei in /dev an. Hierzu befragt es "libsysfs" zu den erforderlichen Geräteinformationen. Die "udev-Regeln" [/etc/udev/rules.d] legen nun z.B. fest, welchen Namen eine Gerätedatei erhält. Hier mal als Beispiel die 70-persistent-net.rule:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:26:18:c9:fb:7d", ATTR{dev_id}=="0x0",  ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Zuerst wird das "SUBSYSTEM" definiert, hier "net", kann "usb", pcmcia" u.a. sein. "ACTION" definiert, was passiert, ist optional. Wenn es fehlt, wird automatisch "add" benutzt. Nach "DRIVERS" können diverse "ATTR(ibutes)" folgen, die das Gerät genauer beschreiben und so eine eindeutige Identifizierung ermöglichen . Das ist wichtig, um z.B. Geräte die zur Laufzeit angesteckt werden, immer mit dem gleichen Namen und oder an der gleichen Stelle einzuhängen. Über den Parameter "RUN+=" können hier auch eigene Skripte ausgeführt werden. Will man nun eine neue udev-Regel erstellen, so kann man sich nach anstecken des entsprechenden Geräts (hier als Beispiel wieder der USB-Stick von oben) die relevanten Attribute anzeigen lassen so nutzt man "udevadm info"

udevadm info --attribute-walk --path=/block/sdb/sdb1

Die Ausgabe kann sehr umfangreich sein, deshalb hier nur ein Auszug:

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
 looking at device '/block/sdb/sdb1':
   KERNEL=="sdb1"
   SUBSYSTEM=="block"
   DRIVER==""
   ATTR{partition}=="1"
   ATTR{start}=="2048"
   ATTR{size}=="2064384"
   ATTR{alignment_offset}=="0"
   ATTR{discard_alignment}=="4293918720"
   ATTR{stat}=="      29        1      240       25        0        0        0        0        0       25       25"
   ATTR{inflight}=="       0        0"
 looking at parent device '/devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0/block/sdb':
   KERNELS=="sdb"
   SUBSYSTEMS=="block"
   DRIVERS==""
   ATTRS{range}=="16"
   ATTRS{ext_range}=="256"
   ATTRS{removable}=="1"
   ATTRS{ro}=="0"
   ATTRS{size}=="2066944"
   ATTRS{alignment_offset}=="0"
   ATTRS{discard_alignment}=="0"
   ATTRS{capability}=="51"
   ATTRS{stat}=="      57        7      512      237        0        0        0        0        0      233      237"
   ATTRS{inflight}=="       0        0"
 looking at parent device '/devices/pci0000:00/0000:00:04.1/usb2/2-5/2-5:1.0/host8/target8:0:0/8:0:0:0':
   KERNELS=="8:0:0:0"
   SUBSYSTEMS=="scsi"
   DRIVERS=="sd"
   ATTRS{device_blocked}=="0"
   ATTRS{type}=="0"
   ATTRS{scsi_level}=="3"
   ATTRS{vendor}=="Generic "
   ATTRS{model}=="Flash Disk      "
   ATTRS{rev}=="8.07"
   ATTRS{state}=="running"
   ATTRS{timeout}=="30"
   ATTRS{iocounterbits}=="32"
   ATTRS{iorequest_cnt}=="0xfe"
   ATTRS{iodone_cnt}=="0xfe"
   ATTRS{ioerr_cnt}=="0x2"
   ATTRS{modalias}=="scsi:t-0x00"
   ATTRS{evt_media_change}=="0"
   ATTRS{queue_depth}=="1"
   ATTRS{queue_type}=="none"
   ATTRS{max_sectors}=="240"
...

Die angegebene Option "--attribute-walk" hangelt sich vom entsprechenden Gerät (/sdb1) den Gerätebaum nach unten entlang bis zur Wurzel (in diesem Fall pci):

 looking at parent device '/devices/pci0000:00/0000:00:04.1':
   KERNELS=="0000:00:04.1"
   SUBSYSTEMS=="pci"
   DRIVERS=="ehci_hcd"
   ATTRS{vendor}=="0x10de"
   ATTRS{device}=="0x077e"
   ATTRS{subsystem_vendor}=="0x1043"
   ATTRS{subsystem_device}=="0x82f2"
   ATTRS{class}=="0x0c0320"
   ATTRS{irq}=="21"
   ATTRS{local_cpus}=="ffffffff"
   ATTRS{local_cpulist}=="0-31"
   ATTRS{modalias}=="pci:v000010DEd0000077Esv00001043sd000082F2bc0Csc03i20"
   ATTRS{dma_mask_bits}=="32"
   ATTRS{consistent_dma_mask_bits}=="32"
   ATTRS{enable}=="1"
   ATTRS{broken_parity_status}=="0"
   ATTRS{msi_bus}==""
   ATTRS{companion}==""
 looking at parent device '/devices/pci0000:00':
   KERNELS=="pci0000:00"
   SUBSYSTEMS==""
   DRIVERS==""

Mit diesen Informationen kann man sich nun sehr genaue Regeln erstellen.

Weiterführende Infos findet man unter [1] und sehr erschöpfend unter [2] (auf Englisch)