Von der Linux Programming Interface , §14.1
Jede Gerätedatei hat eine Haupt-ID-Nummer und eine Neben-ID-Nummer. Die Haupt-ID identifiziert die allgemeine Geräteklasse und wird vom Kernel verwendet, um den entsprechenden Treiber für diesen Gerätetyp zu suchen. Die Neben-ID identifiziert ein bestimmtes Gerät innerhalb einer allgemeinen Klasse eindeutig. Die Haupt- und Neben-IDs einer Gerätedatei werden mit dem Befehl ls -l angezeigt.
[...]
Jeder Gerätetreiber registriert seine Zuordnung zu einer bestimmten Hauptgeräte-ID, und diese Zuordnung stellt die Verbindung zwischen der Gerätespezialdatei und dem Gerät her. Der Name der Gerätedatei hat keine Relevanz, wenn der Kernel nach dem Gerätetreiber sucht.
Siehe auch dieses alte Kapitel (2001) Linux Device Drivers (2e) .
Das heißt, es ist beabsichtigt, für jeden Gerätetyp eine eindeutige Zuordnung von major: minor zu device: instance bereitzustellen. Streng genommen Sie können zwei verschiedene Geräte mit dem gleichen Haupt: minor, solange ein Zeichen ist und man ist Block:
# ls -l /dev/ram1 /dev/mem
crw-r----- 1 root kmem 1, 1 Jan 1 1970 /dev/mem
brw-rw---- 1 root disk 1, 1 Jan 1 1970 /dev/ram1
Unter Linux sind zu jedem Zeitpunkt auf einem System die Haupt-: Nebenzahlen für jeden Gerätetyp eindeutig. Die Zahlen können sich jedoch im Laufe der Zeit ändern und müssen auf verschiedenen Linux-Systemen (sogar auf derselben Distribution, demselben Kernel und derselben Hardware) nicht gleich sein. Beachten Sie, dass Zeichen- und Blockgeräte unterschiedliche Nummerierungsräume haben, z. B. wird Block-Major 1 RAM-Datenträgern zugewiesen, Char-Major 1 wird einer Reihe von Kernel-Geräten zugewiesen, einschließlich Null und Null.
In der Vergangenheit wurden Geräte-Majors (meistens) statisch über eine Registrierung zugewiesen (die in der Kernel-Quelle ebenfalls noch vorhanden ist, obwohl sie nicht verwaltet wird Documentation/devices.txt
). Heutzutage werden viele Geräte dynamisch zugewiesen, dies wird von udev verwaltet und die Zuordnungen können in angezeigt werden /proc/devices
. Die festen Geräte sind noch vorhanden in incude/uapi/linux/major.h
(kürzlich verschoben von include/major.h
)
Obwohl die Kombination major: minor bestimmte Geräteinstanzen eindeutig identifiziert, hindert Sie nichts daran, mehrere Geräteknoten (Dateien) zu erstellen, die auf dasselbe Gerät verweisen. Sie müssen nicht einmal in erstellt werden /dev
(sie müssen sich jedoch in einem Dateisystem befinden, das das Erstellen von Geräteknoten unterstützt und nicht mit der nodev
Option bereitgestellt wird).
Eine häufige Verwendung ist das Erstellen doppelter Null-, Null- und Zufallsgeräte in einer Chroot:
# find /dev /var/chroot -regextype posix-extended -regex ".*/(zero|null|random)" -type c |
xargs ls -l
crwxrwxrwx 1 root root 1, 3 2012-11-21 03:22 /dev/null
crw-rw-r-- 1 root root 1, 8 2012-05-07 10:35 /dev/random
crw-rw-rw- 1 root root 1, 5 2012-11-21 03:22 /dev/zero
crwxrwxrwx 1 root root 1, 3 2012-11-21 03:22 /var/chroot/sendmail/dev/null
crw-rw-r-- 1 root root 1, 8 2012-05-07 10:35 /var/chroot/sendmail/dev/random
crw-rw-rw- 1 root root 1, 5 2012-11-21 03:22 /var/chroot/sendmail/dev/zero
Die Namen sind nur Aliase, der Kernel kümmert sich nicht viel um die meisten Namen oder Speicherorte, er kümmert sich um die Hauptnummer, damit er den richtigen Treiber auswählen kann, und der Treiber kümmert sich (normalerweise) um die Nebennummer, damit er die auswählen kann richtige Instanz.
Die meisten Namen sind einfach Konventionen (obwohl einige von POSIX definiert werden ). Beachten Sie auch, dass sich ein Gerät möglicherweise für mehrere Hauptnummern registriert. Checken Sie den sd
Treiber ein /proc/devices
. Ein Treibermodulname ( .ko
) muss nicht mit dem Gerätenamen und nicht mit dem Geräteknoten identisch sein /dev
, und ein einzelnes Treibermodul kann mehrere logische / physische Geräte oder Gerätenamen verwalten.
Um es noch einmal zusammenzufassen: Sie haben möglicherweise zwei oder mehr Geräteknoten (in /dev/
oder anderswo), die die gleichen Haupt-: Nebennummern haben, aber wenn sie vom gleichen Typ sind, beziehen sie sich auf dasselbe Gerät. Sie können einen Treiber haben, der mehrere Hauptinstanzen verarbeiten kann, aber innerhalb des Kernels und innerhalb des Treibers wird für jeden Typ (char oder block) die Nummer major: minor verwendet, um auf ein bestimmtes Gerät (major) und eine bestimmte Instanz ( Moll) des Geräts.
Sie können nicht zwei Geräteknoten mit demselben Typ und Major haben: Minor und erwarten, dass sie auf zwei verschiedene logische oder physische Geräte zugreifen. Wenn auf ein Gerät zugegriffen wird, wählt der Kernel einen Treiber basierend auf dem Typ und der Hauptnummer (und nicht basierend auf dem Namen des Geräteknotens) aus, und gemäß Konvention wählt die Nebennummer deterministisch eine bestimmte Instanz oder Unterfunktion aus.
Update Eine
interessante Geschichte und eine * BSD-Perspektive finden Sie in der BSDCon- Präsentation 2002 von Poul-Henning Kamp :
https://www.usenix.org/legacy/events/bsdcon/full_papers/kamp/kamp_html/
Wenn Sie in die Zeit von 1978 zurückspringen (mit freundlicher Genehmigung von Alcatel-Lucent, dem Bell System Technical Journal, Juli-August 1978), wird dies im „ Unix Time Sharing System “ klar dargelegt (S. 1937):
Geräte sind durch eine Hauptgerätenummer, eine Nebengerätenummer und eine Klasse (Block oder Zeichen) gekennzeichnet. Für jede Klasse gibt es eine Reihe von Einstiegspunkten in die Gerätetreiber. Die Hauptgerätenummer wird verwendet, um das Array zu indizieren, wenn der Code für einen bestimmten Gerätetreiber aufgerufen wird. Die untergeordnete Gerätenummer wird als Argument an den Gerätetreiber übergeben. Die untergeordnete Zahl hat keine andere Bedeutung als die vom Fahrer zugeschriebene. Normalerweise verwendet der Treiber die untergeordnete Nummer, um auf eines von mehreren identischen physischen Geräten zuzugreifen.