Ich kann cat /dev
, ich kann ls /dev
, ich kann nicht less /dev
. Warum cat
lass ich cat
dieses Verzeichnis aber keine anderen Verzeichnisse?
Ich kann cat /dev
, ich kann ls /dev
, ich kann nicht less /dev
. Warum cat
lass ich cat
dieses Verzeichnis aber keine anderen Verzeichnisse?
Antworten:
In der Vergangenheit (bis V7 UNIX oder um 1979) read
funktionierte der Systemaufruf sowohl für Dateien als auch für Verzeichnisse. read
in 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- ls
Tool genau das getan - read
in 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 readdir
Bibliotheksfunktion 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 read
in 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 readdir
nun 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 readdir
as 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 devfs
Dateisystem, das dem /dev
Mountpoint 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, READDIR
wenn Sie versuchen zu lesen /dev
(das Lesen von Dateien unter /dev
wird von einer separaten Funktion behandelt - devfsspec_read
). Wenn also ein Programm den read
Systemaufruf 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.
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 /dev
es sich um ein devfs
Dateisystem 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.
/etc
an, dass dies der Fall sein würde, also habe ich dies als meine Benchmark verwendet.
mount
oder /sbin/mount
Anzeigen, was aktuell an welcher Stelle gemountet ist.
/dev
es sich um ein virtuelles Dateisystem handelt, das den devfs
Treiber verwendet, während /etc
es Teil des /
Dateisystems ist, das den apfs
Treiber verwendet. Der Grund, warum cat
der eine und nicht der andere lautet, ist ein Unterschied zwischen dem apfs
und den devfs
Treibern.
neofetch
zu Ihrer Information :) i.imgur.com/3azpnDt.png