Warum kann ich cat / dev?

4546
haboutnnah

Ich kann cat /dev, ich kann ls /dev, ich kann nicht less /dev. Warum catlässt mir catdieses Verzeichnis aber keine anderen Verzeichnisse zu?

Bild dieses Verhaltens in zsh.

40
@ KamilMaciorowski, hier ist die Ausgabe und "Neofetch" zu Ihrer Information :) https://i.imgur.com/3azpnDt.png haboutnnah vor 5 Jahren 0

2 Antworten auf die Frage

42
nneonneo

In der Vergangenheit (bis zu V7 UNIX oder um 1979) readfunktionierte der Systemaufruf sowohl für Dateien als auch für Verzeichnisse. readIn einem Verzeichnis würde eine einfache Datenstruktur zurückgegeben, die ein Benutzerprogramm zum Abrufen der Verzeichniseinträge parsen würde. Tatsächlich hat das V7- lsTool genau dies getan - readin einem Verzeichnis die resultierende Datenstruktur parsen, in einem strukturierten Listenformat ausgeben.

Als Dateisysteme komplexer wurden, wurde diese "einfache" Datenstruktur komplizierter bis zu dem Punkt, an dem eine readdirBibliotheksfunktion hinzugefügt wurde, um Programmen zu helfen, die Ausgabe zu analysieren read(directory). Unterschiedliche Systeme und Dateisysteme können unterschiedliche Festplattenformate haben, was immer komplizierter wurde.

Als Sun das Network File System (NFS) einführte, wollten sie die Verzeichnisstruktur auf der Festplatte vollständig abstrahlen. Anstatt ihre read(directory)Rückkehr zu einer plattformunabhängigen Repräsentation des Verzeichnisses zu machen, fügten sie jedoch einen neuen Systemaufruf hinzu - getdirents- und verbot es readfür im Netzwerk eingebundene Verzeichnisse. Dieser Systemaufruf wurde schnell angepasst, um für alle Verzeichnisse in verschiedenen UNIX-Varianten zu funktionieren, wodurch er standardmäßig zum Abrufen des Inhalts der Verzeichnisse verwendet wird. (Historie abstrahiert von https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )

Da readdires jetzt die Standardmethode ist, Verzeichnisse zu lesen, read(directory)wird auf den meisten modernen Betriebssystemen normalerweise kein EISDIR zurückgegeben (QNX ist beispielsweise eine bemerkenswerte Ausnahme, die readdirals implementiert read(directory)). Mit dem "virtuellen Dateisystem" -Design in den meisten modernen Kerneln ist es jedoch Sache des einzelnen Dateisystems, ob das Lesen eines Verzeichnisses funktioniert oder nicht.

Unter macOS unterstützt das devfsdem /devMountpoint zugrunde liegende Dateisystem tatsächlich das Lesen ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629 ). :

static int devfs_read(struct vnop_read_args *ap) { devnode_t * dn_p = VTODN(ap->a_vp);  switch (ap->a_vp->v_type) { case VDIR: { dn_p->dn_access = 1;  return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context); 

Dies wird explizit aufgerufen, READDIRwenn Sie versuchen zu lesen /dev(das Lesen von Dateien unter /devwird von einer separaten Funktion ausgeführt - devfsspec_read). Wenn also ein Programm den readSystemaufruf aufruft /dev, wird es erfolgreich sein und eine Verzeichnisliste erhalten!

Dies ist praktisch eine Funktion, die seit den frühen Tagen von UNIX ein Überbleibsel ist und seit langem nicht mehr angesprochen wurde. Ein Teil von mir vermutet, dass dies aus irgendeinem Grund aus Gründen der Abwärtskompatibilität beibehalten wird, aber es könnte genauso leicht die Tatsache sein, dass sich niemand darum kümmert, das Feature zu entfernen, da es nichts wirklich verletzt.

Wahrscheinlich letzteres, da es aus den meisten Verzeichnissen entfernt wurde. user20574 vor 5 Jahren 0
36
grawity

Weniger ist ein Textdatei-Viewer, cat ist ein Werkzeug zum Kopieren beliebiger Daten. So weniger führt seine eigene Kontrolle, um sicherzustellen, Sie nicht etwas öffnen, die große Mengen an Daten oder verhalten sich sehr seltsam haben. Auf der anderen Seite hat cat keine solche Überprüfung - wenn der Kernel Sie etwas öffnen lässt (selbst wenn es sich um eine Pipe, ein Gerät oder etwas Schlimmeres handelt), wird cat es lesen.

Warum erlaubt das Betriebssystem cat, Verzeichnisse zu öffnen? In BSD-artigen Systemen konnten traditionell alle Verzeichnisse als Dateien gelesen werden. Auf diese Weise würden Programme ein Verzeichnis an erster Stelle auflisten: durch das Interpretieren der auf der Festplatte gespeicherten Strukturstrukturen.

Später lösten sich diese Strukturen auf der Festplatte von dem vom Kernel verwendeten Dirent: Wo zuvor ein Verzeichnis eine lineare Liste war, begannen spätere Dateisysteme mit Hashtables, B-Bäumen usw. Das direkte Lesen von Verzeichnissen war daher nicht mehr so ​​einfach - der Kernel entwickelte dafür dedizierte Funktionen. (Ich bin mir nicht sicher, ob dies der Hauptgrund war oder ob sie hauptsächlich aus anderen Gründen wie dem Caching hinzugefügt wurden.)

In einigen BSD-Systemen können Sie weiterhin alle Verzeichnisse zum Lesen öffnen. Ich weiß nicht, ob sie Ihnen die Rohdaten von der Festplatte geben, oder ob sie stattdessen eine emulierte Störungsliste zurückgeben oder ob sie den Dateisystemtreiber entscheiden lassen.

Vielleicht ist macOS eines dieser Betriebssysteme, bei denen der Kernel dies erlaubt, solange das Dateisystem die Daten liefert. Und der Unterschied ist, dass /deves sich um ein devfsDateisystem handelt, das so geschrieben wurde, dass dies in den frühen Tagen möglich war, während /es sich bei einem APFS-Dateisystem um dieses Feature handelt, das in der heutigen Zeit als unnötig erachtet wird.

Haftungsausschluss: Ich habe noch keine Untersuchungen zu BSDs oder macOS durchgeführt. Ich fliege nur.

Das scheint sinnvoll zu sein. Gibt es andere Speicherbereiche, die sich vom Standard-Dateisystem des Betriebssystems unterscheiden? Ich ging davon aus, dass "/ etc" dies tun würde, also benutzte ich das als Benchmark. haboutnnah vor 5 Jahren 0
Im Gegenteil ist / etc im Allgemeinen nur ein regulärer Ordner, der reguläre Dateien enthält. Es kann jedoch auch andere virtuelle Dateisysteme sein - führen Sie `mount` oder` / sbin / mount` aus, um zu sehen, was momentan wo gemountet ist. grawity vor 5 Jahren 2
Du hast recht! Siehe hierzu: https://i.imgur.com/pcVpo1o.png haboutnnah vor 5 Jahren 0
Das ist wirklich nett @grawity, https://i.imgur.com/8QuR0FK.png haboutnnah vor 5 Jahren 0
Das direkte Lesen einer _Disk_ ist ein ziemlich normaler Vorgang, da Festplatten ohnehin nur eine flache Struktur haben (auf diese Weise können Sie ein .iso-Image von einer CD erstellen). grawity vor 5 Jahren 0
@ Grawity: Ich frage mich, was ist schlimmer :) als ein Gerät zu öffnen, irgendwelche bösartigen Beispiele? ^^ JIV vor 5 Jahren 0
@haboutnnah Ihr Screenshot bestätigt, dass `/ dev` ein virtuelles Dateisystem ist, das den` devfs`-Treiber verwendet, wohingegen `/ etc` Teil des` / `-Dateisystems ist, das den` apfs'-Treiber verwendet. Der Grund, warum "cat" den einen und nicht den anderen liest, ist ein Unterschied zwischen den "apfs" - und "devfs" -Treibern. kasperd vor 5 Jahren 6