Warum kann ich cat / dev?

41

Ich kann cat /dev, ich kann ls /dev, ich kann nicht less /dev. Warum catlass ich catdieses Verzeichnis aber keine anderen Verzeichnisse?

Bild dieses Verhaltens in zsh.

Haboutnnah
quelle
@KamilMaciorowski, hier ist die Ausgabe und neofetchzu Ihrer Information :) i.imgur.com/3azpnDt.png
haboutnnah

Antworten:

43

In der Vergangenheit (bis 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ückgeben, die ein Benutzerprogramm analysieren würde, um die Verzeichniseinträge zu erhalten. In der Tat hat das V7- lsTool genau das getan - readin einem Verzeichnis die resultierende Datenstruktur analysieren und in einem strukturierten Listenformat ausgeben.

Da Dateisysteme immer komplexer wurden, wurde diese "einfache" Datenstruktur immer komplizierter, bis eine readdirBibliotheksfunktion hinzugefügt wurde, mit der Programme die Ausgabe von analysieren können read(directory). Verschiedene Systeme und Dateisysteme haben möglicherweise unterschiedliche Festplattenformate, was immer komplizierter wurde.

Als Sun das Network File System (NFS) einführte, wollte das Unternehmen die Verzeichnisstruktur auf der Festplatte vollständig abstrahieren. Anstatt ihre read(directory)Rückkehr zu einer plattformunabhängigen Darstellung des Verzeichnisses zu machen, fügten sie jedoch einen neuen Systemaufruf hinzu - getdirents- und verbannten sie readin netzwerkmontierten Verzeichnissen. Dieser Systemaufruf wurde schnell an alle Verzeichnisse in verschiedenen UNIX-Varianten angepasst, sodass der Inhalt der Verzeichnisse standardmäßig abgerufen werden konnte. (Verlauf von https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory abstrahiert )

Da dies readdirnun die Standardmethode zum Lesen von Verzeichnissen ist, read(directory)ist sie in den meisten modernen Betriebssystemen normalerweise nicht implementiert (Rückgabe von -EISDIR) (QNX ist beispielsweise eine bemerkenswerte Ausnahme, die readdiras implementiert read(directory)). Beim Entwurf des "virtuellen Dateisystems" 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 devfsDateisystem, das dem /devMountpoint zugrunde liegt, 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 behandelt - devfsspec_read). Wenn also ein Programm den readSystemaufruf aufruft /dev, wird es erfolgreich sein und eine Verzeichnisliste erhalten!

Dies ist praktisch eine Funktion, die sich seit den Anfängen von UNIX erhalten hat und die seit langer Zeit nicht mehr angesprochen wurde. Ein Teil von mir vermutet, dass dies aus Gründen der Abwärtskompatibilität beibehalten wird, aber es könnte genauso gut die Tatsache sein, dass sich niemand genug darum kümmert, das Feature zu entfernen, da es nicht wirklich schadet.

nneonneo
quelle
Wahrscheinlich letzteres, da es aus den meisten Verzeichnissen entfernt wurde.
user253751
36

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

Warum erlaubt das Betriebssystem cat , Verzeichnisse zu öffnen? Traditionell konnten in BSD-artigen Systemen alle Verzeichnisse als Dateien gelesen werden, und auf diese Weise listeten Programme zunächst ein Verzeichnis auf: indem sie nur die auf der Festplatte gespeicherten Verzeichnisstrukturen interpretierten.

Später begannen diese Strukturen auf der Festplatte von dem vom Kernel verwendeten Verzeichnis abzuweichen: Wo zuvor ein Verzeichnis eine lineare Liste war, begannen spätere Dateisysteme, Hashtabellen, B-Bäume usw. zu verwenden. Das direkte Lesen von Verzeichnissen war also nicht mehr ganz einfach - der Kernel erweiterte dafür spezielle Funktionen. (Ich bin mir nicht sicher, ob dies der Hauptgrund war oder ob sie hauptsächlich aus anderen Gründen wie Caching hinzugefügt wurden.)

Bei 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 Verzeichnisliste zurückgeben oder ob sie den Dateisystemtreiber entscheiden lassen.

Vielleicht ist macOS eines der Betriebssysteme, bei denen der Kernel dies zulässt, solange das Dateisystem die Daten bereitstellt. Der Unterschied besteht darin, dass /deves sich um ein devfsDateisystem handelt, das so geschrieben wurde, dass dies in den Anfängen möglich war, während /es sich um ein APFS-Dateisystem handelt, bei dem diese Funktion in der heutigen Zeit nicht mehr erforderlich war.

Haftungsausschluss: Ich habe noch nicht über BSDs oder MacOS recherchiert. Ich schwinge es nur.

Grawity
quelle
Das scheint sinnvoll zu sein. Gibt es andere Speicherbereiche, die sich vom Standarddateisystem des Betriebssystems unterscheiden? Ich nahm /etcan, dass dies der Fall sein würde, also habe ich dies als meine Benchmark verwendet.
Haboutnnah
2
Im Gegensatz dazu ist / etc im Allgemeinen nur ein regulärer Ordner, der reguläre Dateien enthält. Möglicherweise gibt es aber auch andere virtuelle Dateisysteme - Ausführen mountoder /sbin/mountAnzeigen, was aktuell an welcher Stelle gemountet ist.
Grawity
Du hast recht! Siehe hierzu: i.imgur.com/pcVpo1o.png
haboutnnah
Dies ist wirklich ordentlich @grawity, i.imgur.com/8QuR0FK.png
haboutnnah
6
@haboutnnah Ihr Screenshot bestätigt, dass /deves sich um ein virtuelles Dateisystem handelt, das den devfsTreiber verwendet, während /etces Teil des /Dateisystems ist, das den apfsTreiber verwendet. Der Grund, warum catder eine und nicht der andere lautet, ist ein Unterschied zwischen dem apfsund den devfsTreibern.
Kasperd