In der Vergangenheit (bis zu 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ückgegeben, die ein Benutzerprogramm zum Abrufen der Verzeichniseinträge parsen würde. Tatsächlich hat das V7- ls
Tool genau dies getan - read
in 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 readdir
Bibliotheksfunktion 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 read
fü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 readdir
es 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 readdir
als 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 devfs
dem /dev
Mountpoint 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, READDIR
wenn Sie versuchen zu lesen /dev
(das Lesen von Dateien unter /dev
wird von einer separaten Funktion ausgeführt - 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 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.