Pourquoi puis-je chat / dev?


41

Je peux cat /dev, je peux ls /dev, je ne peux pas less /dev. Pourquoi catme laisser catce répertoire mais pas d'autres répertoires?

Image de ce comportement dans zsh.


@KamilMaciorowski, voici le résultat et neofetchpour votre information :) i.imgur.com/3azpnDt.png
haboutnnah

Réponses:


43

Historiquement (jusqu’à VIX UNIX ou autour de 1979), l’ readappel système fonctionnait à la fois pour les fichiers et les répertoires. readsur un répertoire renverrait une simple structure de données qu'un programme utilisateur analyserait pour obtenir les entrées du répertoire. En effet, l' lsoutil V7 a fait exactement cela - readsur un répertoire, analyser la structure de données résultante, sortie dans un format de liste structurée.

À mesure que les systèmes de fichiers se complexifiaient, cette structure de données "simple" devenait de plus en plus compliquée, au point qu'une readdirfonction de bibliothèque a été ajoutée pour aider les programmes à analyser la sortie de read(directory). Différents systèmes et systèmes de fichiers pouvaient avoir différents formats sur disque, ce qui devenait compliqué.

Lorsque Sun a introduit le système de fichiers réseau (Network File System ou NFS), ils ont voulu supprimer complètement la structure de répertoires sur disque. Au lieu de faire de leur read(directory)retour une représentation du répertoire indépendante de la plate-forme, ils ont ajouté un nouvel appel système getdirents- et ont interdit readles répertoires montés sur le réseau. Cet appel système a été rapidement adapté pour fonctionner sur tous les répertoires de différentes versions d'UNIX, ce qui en fait le moyen par défaut d'obtenir le contenu des répertoires. (Histoire extraite de https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )

Parce que readdirc’est maintenant le moyen par défaut de lire les répertoires, il read(directory)n’est généralement pas implémenté (renvoyer -EISDIR) sur la plupart des systèmes d’exploitation modernes (QNX, par exemple, est une exception notable qui s’implémente en readdirtant que read(directory)). Cependant, avec la conception "système de fichiers virtuel" dans la plupart des noyaux modernes, il appartient au système de fichiers individuel de savoir si la lecture d'un répertoire fonctionne ou non.

Et en effet, sur macOS, le devfssystème de fichiers sous-jacent au point de /devmontage supporte réellement la lecture ( 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);

Cela appelle explicitement READDIRsi vous essayez de lire /dev(la lecture de fichiers sous /devest gérée par une fonction séparée - devfsspec_read). Donc, si un programme appelle l' readappel système /dev, il réussira et obtiendra une liste de répertoires!

C’est effectivement une fonctionnalité qui a été conservée depuis les tout débuts d’UNIX et qui n’a pas été touchée depuis très longtemps. Une partie de moi pense que cela est conservé pour des raisons de compatibilité ascendante, mais cela pourrait tout aussi bien être le fait que personne ne se soucie assez de supprimer cette fonctionnalité car elle ne blesse pas vraiment.


Probablement ce dernier, vu qu'il a été supprimé de la plupart des répertoires.
user253751

36

Less est une visionneuse de fichiers texte, cat est un outil de copie de données arbitraires. Donc, less effectue sa propre vérification pour s'assurer que vous n'ouvrez pas quelque chose qui contient des quantités énormes de données ou se comporte de façon très étrange. Par contre, cat n'a aucune vérification de ce type - si le noyau vous permet d'ouvrir quelque chose (même s'il s'agit d'un tuyau, d'un périphérique ou de quelque chose de pire), cat le lira.

Alors, pourquoi le système d'exploitation permet-il à cat d'ouvrir des répertoires? Traditionnellement, dans les systèmes de type BSD, tous les répertoires pouvaient être lus sous forme de fichiers, et c’était ainsi que les programmes listaient un répertoire: en interprétant simplement les structures dirent stockées sur disque.

Plus tard, ces structures sur disque ont commencé à diverger du sens utilisé par le noyau: là où un répertoire était auparavant une liste linéaire, les systèmes de fichiers ultérieurs ont commencé à utiliser des hashtables, des B-trees, etc. Donc, la lecture directe des répertoires n’était plus simple: le noyau a développé des fonctions dédiées à cette fin. (Je ne sais pas si c'était la raison principale ou s'ils ont été ajoutés principalement pour d'autres raisons, telles que la mise en cache.)

Certains systèmes BSD continuent de vous permettre d'ouvrir tous les répertoires en lecture. Je ne sais pas s'ils vous donnent les données brutes du disque, ou s'ils renvoient une liste de dirents émulés, ou s'ils laissent le pilote du système de fichiers décider.

Donc, peut-être que macOS est l’un de ces systèmes d’exploitation où le noyau le permet, à condition que le système de fichiers fournisse les données. Et la différence est que /devc'est sur un devfssystème de fichiers qui a été écrit pour permettre cela dans les premiers jours, alors qu'il /est sur un système de fichiers APFS qui a omis cette fonctionnalité car inutile dans les temps modernes.

Clause de non-responsabilité: Je n'ai pas encore effectué de recherche sur les BSD ou MacOS. Je ne fais que m'envoler.


Cela semble avoir du sens. Existe-t-il d'autres sections de stockage qui diffèrent du système de fichiers standard du système d'exploitation? J'ai supposé /etcque, alors j'ai utilisé cela comme point de repère.
haboutnnah

2
Au contraire, généralement / etc n’est qu’un dossier normal contenant des fichiers ordinaires. Il peut toutefois y avoir d’autres systèmes de fichiers virtuels - exécutez mountou /sbin/mountconsultez ce qui est actuellement monté.
Grawity

Tu as raison! Voir ceci: i.imgur.com/pcVpo1o.png
haboutnnah

C'est vraiment chouette @
haboutnnah

6
@haboutnnah Votre capture d'écran confirme qu'il /devs'agit d'un système de fichiers virtuel utilisant le devfspilote, alors qu'il /etcfait partie du /système de fichiers utilisant le apfspilote. Donc, la raison catlira l’un et pas l’autre une différence entre les pilotes apfset devfs.
Kasperd
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.