Dies ist eine eher einfache Frage, und ich verstehe, dass dies möglicherweise nicht der beste Ort ist, um sie zu stellen. Aber es schien angemessener zu sein als jede andere SE-Site.
Ich weiß, dass auf dem Linux-Dateisystem tatsächlich einige Dateien existieren , zum Beispiel: /usr/bin/bash
ist eine, die existiert. Allerdings (soweit ich es verstehe), einige haben auch nicht wirklich existieren als solche und sind virtuelle Dateien, zum Beispiel: /dev/sda
, /proc/cpuinfo
usw. Meine Fragen sind (sie sind zwei, aber zu eng verwandt getrennten Fragen zu sein):
- Wie ermittelt der Linux-Kernel, ob diese Dateien echt sind (und sie daher von der Festplatte lesen) oder nicht, wenn ein Lesebefehl (oder ein solcher) ausgegeben wird?
- Wenn die Datei nicht echt ist: Als Beispiel gibt ein Lesevorgang
/dev/random
zufällige Daten zurück und ein Lesevorgang/dev/null
wird zurückgegebenEOF
. Wie wird ermittelt, welche Daten aus dieser virtuellen Datei gelesen werden sollen (und was ist daher zu tun, wenn / wenn Daten auch in die virtuelle Datei geschrieben werden)? oder sogar für das virtuelle Verzeichnis selbst? Ein Eintrag für/dev/null
könnte also einfach einen zurückgebenEOF
.
Antworten:
Es gibt hier also grundsätzlich zwei verschiedene Arten von Dingen:
/proc
und/sys
sind hier Beispiele, ebenso wie benutzerdefinierte FUSE-Dateisysteme wiesshfs
oderifuse
. Es gibt viel mehr Vielfalt in diesen, weil sie sich in Wirklichkeit nur auf ein Dateisystem mit einer Semantik beziehen, die in gewissem Sinne "benutzerdefiniert" ist. Wenn Sie also aus einer Datei unter lesen/proc
, greifen Sie nicht auf ein bestimmtes Datenelement zu, das von einer anderen Person gespeichert wurde, die es zuvor geschrieben hat, wie unter einem normalen Dateisystem. Sie führen im Wesentlichen einen Kernel-Aufruf durch und fordern einige Informationen an, die im laufenden Betrieb generiert werden. Und dieser Code kann alles tun, was er will, da er nur eine Funktion ist, die irgendworead
Semantik implementiert . So haben Sie das seltsame Verhalten von Dateien unter/proc
, wie zum Beispiel vorzugeben, Symlinks zu sein, wenn sie nicht vorhanden sind.Der Schlüssel ist, dass
/dev
es sich in der Regel um eine der ersten Arten handelt. In modernen Distributionen/dev
ist es normal, so etwas wie ein tmpfs zu haben, aber in älteren Systemen war es normal, dass es ein einfaches Verzeichnis auf der Festplatte ohne spezielle Attribute war. Der Schlüssel ist, dass die Dateien darunter/dev
Geräteknoten sind, eine Art Spezialdatei, die FIFOs oder Unix-Sockets ähnelt. Ein Geräteknoten hat eine Haupt- und eine Nebennummer. Wenn Sie diese lesen oder schreiben, rufen Sie einen Kerneltreiber auf. Ähnlich wie beim Lesen oder Schreiben eines FIFOs wird der Kernel aufgerufen, um Ihre Ausgabe in einer Pipe zu puffern. Dieser Treiber kann tun, was er will, berührt jedoch normalerweise die Hardware, z. B. um auf eine Festplatte zuzugreifen oder den Ton in den Lautsprechern wiederzugeben.So beantworten Sie die ursprünglichen Fragen:
Es gibt zwei relevante Fragen, ob die 'Datei existiert' oder nicht; Dies ist, ob die Geräteknotendatei buchstäblich existiert und ob der Kernel-Code, der sie sichert, von Bedeutung ist. Ersteres wird wie alles in einem normalen Dateisystem aufgelöst. Moderne Systeme verwenden
udev
oder ähnliches, um Hardwareereignisse zu beobachten und die Geräteknoten unter den/dev
entsprechenden Bedingungen automatisch zu erstellen und zu zerstören . Bei älteren Systemen oder leichten benutzerdefinierten Builds können jedoch alle Geräteknoten buchstäblich auf der Festplatte gespeichert und vorab erstellt werden. Währenddessen rufen Sie beim Lesen dieser Dateien den Kernel-Code auf, der von den Haupt- und Nebengerätenummern bestimmt wird. Wenn dies nicht zumutbar ist (wenn Sie beispielsweise versuchen, ein nicht vorhandenes Block-Gerät zu lesen), wird nur eine Art E / A-Fehler ausgegeben.Die Art und Weise, wie ermittelt wird, welcher Kernelcode für welche Gerätedatei aufzurufen ist, variiert. Für virtuelle Dateisysteme
/proc
implementieren sie ihre eigenenread
undwrite
Funktionen. Der Kernel ruft diesen Code nur auf, je nachdem, auf welchem Mount-Punkt er sich befindet. Den Rest erledigt die Implementierung des Dateisystems. Bei Gerätedateien erfolgt der Versand basierend auf den Haupt- und Nebengerätenummern.quelle
/dev
wären die darin enthaltenen Dateien immer noch vorhanden, aber ich vermute, sie würden gelöscht, wenn das System gestartet wird.tmpfs
würde sie nach Bedarf dynamisch erstellen und löschen, z. B .: Booten und Herunterfahren?devtmpfs
, das/dev
Dateisystem in modernem Linux, ähnelt atmpfs
, weist jedoch einige Unterschiede auf, die unterstützt werden müssenudev
. (Der Kernel führt einige automatisierte Knotenerstellungen aus, bevor er an übergibtudev
, um das Booten zu vereinfachen.) In all diesen Fällen befinden sich Geräteknoten nur im RAM und werden dynamisch erstellt und zerstört, wenn die Hardware dies erfordert. Vermutlich könnte man es auchudev
auf einer normalen Festplatte verwenden/dev
, aber ich habe das noch nie gesehen und es scheint keine guten Gründe dafür zu geben.Hier ist eine Dateiliste von
/dev/sda1
meinem fast aktuellen Arch Linux-Server:Der Verzeichniseintrag in
/dev/
forsda
hat also die Inode-Nummer 1294. Es ist eine echte Datei auf der Festplatte.Sehen Sie sich an, wo normalerweise die Dateigröße angezeigt wird. Stattdessen wird "8, 1" angezeigt. Dies ist eine Haupt- und Nebengerätenummer. Beachten Sie auch das 'b' in den Dateiberechtigungen.
Die Datei
/usr/include/ext2fs/ext2_fs.h
enthält diese (Fragment-) C-Struktur:Diese Struktur zeigt uns die Festplattenstruktur des Inodes einer Datei. In dieser Struktur stecken viele interessante Dinge; werfen Sie einen langen Blick darauf.
Das
i_mode
Element vonstruct ext2_inode
hat 16 Bits und verwendet nur 9 für Benutzer / Gruppe / Andere, Lese- / Schreib- / Ausführungsberechtigungen und weitere 3 für Setuid, Setgid und Sticky. Es gibt 4 Bits zur Unterscheidung zwischen den Typen "Plain File", "Link", "Directory", "Named Pipe", "Unix Family Socket" und "Block Device".Der Linux-Kernel kann dem üblichen Verzeichnissuchalgorithmus folgen und dann basierend auf den Berechtigungen und Flags im
i_mode
Element eine Entscheidung treffen . Bei 'b', Gerätedateien blockieren, werden die Haupt- und Nebengerätenummern gefunden, und traditionell wird anhand der Hauptgerätenummer ein Zeiger auf eine Kernelfunktion (einen Gerätetreiber) gesucht, die sich mit Datenträgern befasst. Die untergeordnete Gerätenummer wird normalerweise als beispielsweise die SCSI-Bus-Gerätenummer oder die EIDE-Gerätenummer oder ähnliches verwendet.Einige andere Entscheidungen, wie mit einer Datei umgegangen
/proc/cpuinfo
werden soll, werden basierend auf dem Dateisystemtyp getroffen. Wenn Sie Folgendes tun:Sie können sehen, dass
/proc
das Dateisystem den Typ "proc" hat. Das Einlesen einer Datei/proc
bewirkt, dass der Kernel je nach Typ des Dateisystems etwas anderes ausführt, als das Öffnen einer Datei in einem ReiserFS- oder DOS-Dateisystem dazu führt, dass der Kernel verschiedene Funktionen zum Suchen von Dateien und zum Auffinden von Daten der Datei verwendet Dateien.quelle
4026531975 -r--r--r-- 1 root root 0 Nov 14 18:41 /proc/mdstat
was eindeutig keine "echte Datei" ist.Am Ende des Tages sind sie alle Dateien für Unix, das ist das Schöne an der Abstraktion.
Die Art und Weise, wie der Kernel mit den Dateien umgeht, ist eine andere Geschichte.
/ proc und heutzutage / dev und / run (aka / var / run) sind virtuelle Dateisysteme im RAM. / proc ist eine Schnittstelle / ein Fenster zu Kernelvariablen und -strukturen.
Ich empfehle The Linux Kernel http://tldp.org/LDP/tlk/tlk.html und Linux Device Drivers, Third Edition https://lwn.net/Kernel/LDD3/ zu lesen .
Mir hat auch das Design und die Implementierung des FreeBSD-Betriebssystems gefallen http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1
Schauen Sie sich die relevante Seite an, die zu Ihrer Frage gehört.
http://www.tldp.org/LDP/tlk/dd/drivers.html
quelle
Zusätzlich zu den Antworten von @ RuiFRibeiro und @ BruceEdiger unterscheidet sich der Kernel nicht genau. Tatsächlich gibt es verschiedene Arten von Dateien: normale Dateien, Verzeichnisse, symbolische Links, Geräte, Sockets (und ich vergesse immer einige, damit ich nicht versuche, eine vollständige Liste zu erstellen). Sie können die Informationen über den Typ einer Datei erhalten,
ls
indem Sie Folgendes eingeben : Es ist das erste Zeichen in der Zeile. Beispielsweise:Das 'b' ganz am Anfang signalisiert, dass diese Datei ein Blockgerät ist. Ein Bindestrich bedeutet eine reguläre Datei, eine symbolische Verknüpfung und so weiter. Diese Informationen werden in den Metadaten der Datei gespeichert und sind beispielsweise über den Systemaufruf zugänglich
stat
, sodass der Kernel beispielsweise eine Datei und einen symbolischen Link unterschiedlich lesen kann.Dann machen Sie eine weitere Unterscheidung zwischen "echten"
/bin/bash
und "virtuellen" Dateien,/proc/cpuinfo
aber gebenls
beide als reguläre Dateien an, sodass der Unterschied anders ist:Was passiert ist, dass sie zu verschiedenen Dateisystemen gehören.
/proc
ist der Einhängepunkt eines Pseudo-Dateisystems,procfs
wohingegen er/bin/bash
sich auf einem regulären Festplatten-Dateisystem befindet. Wenn Linux eine Datei öffnet (dies ist je nach Dateisystem unterschiedlich), wird eine Datenstruktur aufgefüllt,file
die unter anderem eine Struktur aus mehreren Funktionszeigern enthält, die die Verwendung dieser Datei beschreiben. Daher können unterschiedliche Verhaltensweisen für verschiedene Dateitypen implementiert werden.Dies sind beispielsweise die Vorgänge, die angekündigt werden von
/proc/meminfo
:Wenn Sie sich die Definition von ansehen
meminfo_proc_open
, können Sie sehen, dass diese Funktion einen Puffer im Speicher mit den von der Funktion zurückgegebenen Informationen fülltmeminfo_proc_show
, deren Aufgabe es ist, Daten über die Speichernutzung zu sammeln. Diese Informationen können dann normal gelesen werden. Bei jedem Öffnen der Datei wird die Funktionmeminfo_proc_open
aufgerufen und die Informationen zum Speicher werden aktualisiert.quelle
Alle Dateien in einem Dateisystem sind "real" in dem Sinne, dass sie Datei-E / A ermöglichen. Wenn Sie eine Datei öffnen, erstellt der Kernel einen Dateideskriptor, bei dem es sich um ein Objekt (im Sinne einer objektorientierten Programmierung) handelt, das sich wie eine Datei verhält. Wenn Sie die Datei lesen, führt der Dateideskriptor seine Lesemethode aus, die das Dateisystem (sysfs, ext4, nfs usw.) nach Daten aus der Datei fragt. Die Dateisysteme bieten eine einheitliche Benutzeroberfläche und wissen, wie mit Lese- und Schreibvorgängen umzugehen ist. Die Dateisysteme fordern wiederum andere Ebenen auf, ihre Anforderungen zu bearbeiten. Bei einer regulären Datei auf beispielsweise einem ext4-Dateisystem müssen die Datenstrukturen des Dateisystems nachgeschlagen werden (dies kann Festplattenlesevorgänge umfassen), und schließlich muss ein Lesevorgang von der Festplatte (oder dem Cache) durchgeführt werden, um Daten in den Lesepuffer zu kopieren. Für eine Datei in say sysfs, Es ist im Allgemeinen nur sprintf () etwas in den Puffer. Bei einem Block-Dev-Knoten fordert er den Plattentreiber auf, einige Blöcke zu lesen und in den Puffer zu kopieren (die Haupt- und Nebennummern teilen dem Dateisystem mit, an welchen Treiber Anforderungen gestellt werden sollen).
quelle