7.4. Umgang mit Geräten und Modulen an einem LFS-System

In Kapitel 6 haben Sie Udev installiert. Bevor wir zu den Details kommen wie das alles funktioniert, möchten wir Ihnen erst einen Rückblick darüber geben, wie man früher mit Geräten unter Linux umgegangen ist.

Traditionell hat man unter Linux eine statische Methode zum Erzeugen von Gerätedateien benutzt. Dabei wurden sehr viele Gerätedateien vorab in /dev erzeugt (manchmal mehrere tausend). Dabei war es völlig egal, ob die zugehörige Hardware tatsächlich existierte oder nicht. Dies wurde typischerweise durch das Skript MAKEDEV erledigt, welches eine Menge Systemaufrufe mit dem Programm mknod und den entsprechenden Gerätenummern durchführte und so Gerätedateien zu allen erdenklichen Geräten erzeugte.

Mit der Udev-Methode werden nur die Gerätedateien erzeugt, zu denen der Kernel auch ein Gerät gefunden hat. Weil diese Gerätedateien bei jedem Systemstart neu erzeugt werden, speichert man sie auf einem sog. tmpfs-Dateisystem. Dieses Dateisystem existiert nur im Arbeitsspeicher und verbraucht daher keinen Festplattenplatz. Gerätedateien benötigen kaum Platz, auf diese Weise wird also nur sehr wenig Arbeitsspeicher verbaucht.

7.4.1. Die Entwicklungsgeschichte von Udev

Im Februar 2000 wurde ein neues Dateisystem mit dem Namen devfs in den Kernel 2.3.46 integriert und dann in der 2.4er Serie der stabilen Kernel verfügbar gemacht. Obwohl es in den Kernelquellen selbst verfügbar war, hat diese Methode nie wirkliche Unterstützung von den Kernel-Entwicklern bekommen.

Das Haupt-Problem bei diesem von devfs adaptierten Ansatz war die Art und Weise, auf die Geräte erkannt, erzeugt und benannt wurden. Letzteres (Namensvergabe) war wohl das kritischste Problem. Das Dateisystem devfs litt außerdem unter sog. Race conditions, die mit dem Konzept zusammenhingen und nur durch nennenswerte Änderungen am Kernel geändert werden konnten. Des Weiteren war es für lange Zeit als „missbilligt“ markiert, weil es nicht gepflegt wurde – schlussendlich wurde es im Juni 2006 ganz aus dem Kernel entfernt.

Mit der Enticklung der 2.5er Entwickler-Kernelserie, die später als stabile 2.6er-Serie veröffentlicht wurde, wurde ein neues Dateisystem mit dem Namen sysfs eingeführt. Die Aufgabe von sysfs ist es, die Betriebssystemstruktur an Anwenderprozesse zu exportieren. Mit dieser aus der Anwenderschicht sichtbaren Repräsentation des Betriebssystems kam ein Ersatz für devfs in Sichtweite.

7.4.2. Udev-Implementierung

7.4.2.1. Sysfs

Das Dateisystem sysfs wurde oben schon kurz erwähnt. Man fragt sich vielleicht, woher sysfs von den Geräten und den zu verwendenden Gerätenummern weiß: Treiber, die direkt in den Kernel integriert wurden, registrieren sich bei sysfs sobald sie vom Kernel erkannt werden. Bei Kernel-Modulen geschieht dieser Vorgang beim Laden des Moduls. Sobald sysfs in das System eingehängt ist (unter /sys), sind die Daten von den mit sysfs registrierten Treibern für Prozesse aus der Anwenderschicht, und damit auch für udev, verfügbar.

7.4.2.2. Das Udev-Bootskript

Das Bootskript S10udev kümmert sich um das Erstellen von Gerätedateien beim Systemstart. Das Skript entfernt /sbin/hotplug als Verantwortliches Skript für uevents, weil der Kernel kein externes Programm mehr benötigt. Stattdessen wartet udevd an einem Netlink-Socket auf uevents des Kernels. Als nächstes kopiert das Bootskript statische Gerätedateien von /lib/udev/devices nach /dev. Dies ist wichtig, weil einige Gerätedateien, Ordner und symbolische Links beim Bootvorgang oder von udevd selbst benötigt werden, bevor die dynamische Geräteerstellung von Udev betriebsbereit ist. Durch Einrichten von statischen Gerätedateien in /lib/udev/devices kann man auch Gerätedateien unterstützen, die normalerweise nicht von Udev automatisch angelegt werden würden. Als nächstes startet das Bootskript den Udev-Daemon udevd, der von nun an auf uevents wartet und reagiert. Schlussendlich zwingt das Bootskript den Kernel, die uevents für Geräte zu wiederholen, die sich vor dem Start von udevd registriert haben.

7.4.2.3. Erzeugen von Gerätedateien

Udev verlässt sich auf die Informationen von sysfs in /sys und liest daraus die Haupt- und Unterkennung für Gerätedateien aus. Beispielsweise enthält /sys/class/tty/vcs/dev den Text „7:0“. Diesen Wert interpretiert udevd und erzeugt eine Gerätedatei mit der Hauptkennung 7 und der Unterkennung 0. Die Namen und Berechtigungen für die in /dev erzeugten Gerätedateien ergeben sich aus den definierten Regeln in /etc/udev/rules.d/. Die dort abgelegten Regeln sind ähnlich nummeriert wie die Dateien der LFS-Bootskripte. Falls udevd keine Regel für ein erzeugtes Gerät auffinden kann, ist die Voreinstellung für die Berechtigungen 660 und die Gerätedatei gehört root:root. Eine genauere Dokumentation zu den Konfigurationsdateien von Udev finden Sie unter /usr/share/doc/udev-130/index.html.

7.4.2.4. Laden von Modulen

Als Modul kompilierte Gerätetreiber können Aliase eingebaut haben. Diese kann man sich mit dem Kommando modinfo ansehen und hängen üblicherweise mit den Bus-Spezifischen Kennmarken eines vom Treiber unterstützten Gerätes zusammen. Beispielsweise unterstützt der Treiber snd-fm801 PCI-Geräte mit der Hersteller-ID 0x1319 und Geräte-ID 0x0801. Der zugehörige Alias lautet „pci:v00001319d00000801sv*sd*bc04sc01i*“. Für die meisten Geräte exportiert der Bus-Treiber den Alias des notwendigen Treibers nach sysfs. So würde beispielsweise die Datei /sys/bus/pci/devices/0000:00:0d.0/modalias den Wert „pci:v00001319d00000801sv00001319sd00001319bc04sc01i00“ enthalten. Die Standard-Udev-Regeln sorgen dafür, dass udevd /sbin/modprobe mit dem Inhalt der uevent-Umgebungsvariable MODALIAS aufruft (sie sollte das Gleiche enthalten wie die Datei modalias in sysfs). Dadurch werden alle Module aufgerufen, deren Alias dem Wert entsprechen.

In diesem Beispiel bedeutet das aber auch, dass zusätzlich zu snd-fm801 noch er veraltete (und unerwünschte) Treiber forte geladen wird, sofern er verfügbar ist. Weiter unten ist eine Möglichkeit beschrieben, wie man das Laden unerwünschter Treiber verhindern kann.

Der Kernel selbst ist ebenfalls in der Lage, Module für Netzwerkprotokolle, Dateisystem und NLS nach Bedarf zu laden.

7.4.2.5. Der Umgang mit dynamischen bzw. Hotplug-Geräten

Wenn Sie ein Gerät wie beispielsweise einen USB-MP3-Player, so erkennt der Kernel ein neu angeschlossenes Gerät und erzeugt einen uevent. Um dieses neue uevent kümmert sich dann udevd so wie oben beschrieben.

7.4.3. Probleme mit dem Laden von Kernelmodulen und dem Erzeugen von Gerätedateien

Es gibt ein paar mögliche Probleme beim automatisierten Erzeugen von Gerätedateien:

7.4.3.1. Das nötige Kernelmodul wird nicht automatisch geladen

Udev lädt nur dann ein Modul, wenn ein Bus-Spezifischer Alias vorhanden ist und der Treiber die nötigen Aliase korrekt nach sysfs exportiert. Wenn dies nicht der Fall ist, muss man sich auf andere Weise um das Laden des Moduls kümmern. Mit Linux-2.6.27.4 kann Udev korrekt programmierte Treiber für INPUT-, IDE-, PCI-, USB-, SCSI-, SERIO- und FireWire-Geräte laden.

Mit dem Kommando modinfo und dem Modulnamen als Argument können Sie herausfinden, ob der von Ihnen benötigte Treiber von Udev unterstützt wird. Versuchen Sie nun, den Geräte-Ordner unter /sys/bus zu finden und prüfen Sie die dortige Datei modalias.

Wenn die Datei modalias unter sysfs vorhanden ist und der Treiber das Gerät unterstützt, aber der Alias fehlt, so ist dies ein Fehler im Treiber. Dann müssen Sie den Treiber ohne Hilfe von Udev laden und darauf hoffen, dass dieser Fehler später behoben wird.

Wenn die Datei modalias in dem zugehörigen Ordner unter /sys/bus nicht vorhanden ist, so haben die Kernel-Entwickler für diesen Bus-Typ noch keine Modalias-Unterstützung programmiert. Bei Linux-2.6.27.4 ist dies z. B. der Fall für den ISA-Bus. Dies wird wahrscheinlich in einer zukünftigen Kernelversion behoben.

Udev sorgt sich nicht um das Laden sogenannter „wrapper“-Treibern wie beispielsweise snd-pcm-oss oder Nicht-Hardware-Treibern wie loop.

7.4.3.2. Ein Kernelmodul lädt nicht automatisch und Udev ist nicht dafür zuständig

Wenn ein „Wrapper“-Modul nur die Funktionen eines anderen Moduls erweitert (so erweitert z. B. das Modul snd-pcm-oss die Funktionalität von snd-pcm indem es die Soundkarte auch OSS-Anwendungen zur Verfügung stellt), dann richten Sie modprobe so ein, dass es das Wrapper-Modul lädt, nachdem Udev das Hauptmodul geladen hat. Dies erreichen Sie mit einer „install“-Anweisung in /etc/modprobe.conf. Beispiel:

install snd-pcm /sbin/modprobe -i snd-pcm ; \
    /sbin/modprobe snd-pcm-oss ; true

Wenn es sich bei dem fraglichen Modul nicht um einen Wrapper handelt sondern alleinstehend geladen wird, so richten Sie bitte das Bootskript S05modules ein, sodass das Modul beim Booten geladen wird. Dies erreichen Sie, indem Sie den Modulnamen an die Datei /etc/sysconfig/modules in einer eigenen Zeile anhängen. Dies funktioniert natürlich auch mit Wrapper-Modulen, ist aber nicht optimal.

7.4.3.3. Udev lädt unerwünschte Module

Entweder Sie kompilieren das fragliche Modul gar nicht erst, oder Sie schließen es mit Hilfe der schwarzen Liste in /etc/modprobe.conf aus, so wie mit dem Modul forte im folgenden Beispiel:

blacklist forte

Module auf der schwarzen Liste können natürlich weiterhin von Hand mit dem Programm modprobe geladen werden.

7.4.3.4. Udev erzeugt eine Gerätedatei falsch oder setzt einen falschen symbolischen Link

Dies geschieht für gewöhnlich, wenn eine Regel versehentlich auf ein anderes Gerät passt, als vorgesehen. Eine schlecht geschriebene Regel könnte z. B. sowohl auf eine SCSI-Festplatte (wie gewünscht) als auch auf das zugehörige generische SCSI-Gerät (unerwünscht) nach dem Hersteller passen. Sie müssen die Regel auffinden und genauer ausformulieren (dabei hilft Ihnen der Befehl udevadm info).

7.4.3.5. Udev funktioniert nur unzuverlässig

Dies ist zumeist nur ein weiteres Symptom des zuvor beschriebenen Problems. Falls nicht, und die betreffende Regel sysfs-Attribute verwendet, so könnte es sich um Kernel-Zeitprobleme handeln, die erst in zukünftigen Kernelversionen behoben werden. Sie können das Problem umgehen, indem Sie eine Regel schreiben, die erst auf das verwendete sysfs-Attribut wartet und fügen Sie an /etc/udev/rules.d/10-wait_for_sysfs.rules an (erzeugen Sie die Datei, falls sie noch nicht existiert). Wenn Sie dies tun, informieren Sie bitte das LFS-Entwicklerteam darüber und teilen Sie uns auch mit, ob dies funktioniert.

7.4.3.6. Udev erzeugt eine Gerätedatei nicht

Im folgenden Text wird davon ausgegangen, dass der Treiber entweder statisch in den Kernel eingebaut ist, oder das Modul bereits geladen ist. Außerdem sollten Sie überprüft haben, ob nicht möglicherweise nur eine Gerätedatei mit falschen Namen erzeugt wurde.

Udev hat nicht genügen Informationen zum Erzeugen einer Gerätedatei, wenn der Kerneltreiber seine Daten nicht ins sysfs exportiert. Dies ist bei Treibern von Drittherstellern außerhalb des Kernelbaums leider öfter der Fall. Erzeugen Sie eine statische Gerätedatei mit der korrekten Haupt- und Unterkennung in /lib/udev/devices. Ziehen Sie dazu auch die Datei devices.txt aus der Kernel-Dokumentation zu Rate oder lesen Sie die Dokumentation des Drittherstellers. Diese statische Gerätedatei wird dann beim Bootvorgang von S10udev nach /dev kopiert.

7.4.3.7. Die Reihenfolge der Gerätenamen ändert sich mit jedem Bootvorgang

Dies liegt daran, dass Udev (gewollt und ganz bewusst) alle uevents parallel — und somit in unterschiedlicher Reihenfolge — abarbeitet. Dieses Phänomen wird niemals „repariert“ werden. Verlassen Sie sich nicht auf die Gerätenamen des Kernels. Schreiben Sie stattdessen Regeln, die aussagekräftige symbolische Links mit stabilen Namen erzeugen. Dazu können Sie Attribute zu Geräten heranziehen, wie z B. Seriennummern oder die Ausgabe der verschiedenen *_id-Hilfsprogramme von Udev. Schauen Sie für einige Beispiele unter Abschnitt 7.12, „Erzeugen von benutzerdefinierten symbolischen Links zu Geräten“Abschnitt 7.13, „Einrichten des network-Skripts“ nach.

7.4.4. Nützliche Dokumentation

Weitere hilfreiche Dokumentation finden Sie an den folgenden Stellen: