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.
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.
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.
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.
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
.
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.
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.
Es gibt ein paar mögliche Probleme beim automatisierten Erzeugen von Gerätedateien:
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.
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.
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.
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).
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.
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.
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.
Weitere hilfreiche Dokumentation finden Sie an den folgenden Stellen:
A Userspace Implementation of devfs
http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
udev FAQ http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ
The sysfs
Filesystem
http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf