J'ai lu comment les canaux sont implémentés dans le noyau Linux et je voulais valider ma compréhension. Si je me trompe, la réponse avec l'explication correcte sera sélectionnée.
- Linux a un VFS appelé pipefs qui est monté dans le noyau (pas dans l'espace utilisateur)
- pipefs a un seul super bloc et est monté à sa propre racine (
pipe:
), à côté de/
- les pipefs ne peuvent pas être visualisés directement contrairement à la plupart des systèmes de fichiers
- L'entrée dans pipefs se fait via le
pipe(2)
syscall - L'
pipe(2)
appel système utilisé par les shells pour la tuyauterie avec l'|
opérateur (ou manuellement à partir de tout autre processus) crée un nouveau fichier dans pipefs qui se comporte à peu près comme un fichier normal - Le fichier sur le côté gauche de l'opérateur de tuyau est
stdout
redirigé vers le fichier temporaire créé dans pipefs - Le fichier sur le côté droit de l'opérateur de tuyau a son
stdin
jeu dans le fichier sur les pipefs - pipefs est stocké en mémoire et grâce à la magie du noyau, ne doit pas être paginé
Cette explication du fonctionnement des tuyaux (par exemple ls -la | less
) est-elle à peu près correcte?
Une chose que je ne comprends pas, c'est comment quelque chose comme bash définirait un processus ' stdin
ou stdout
le descripteur de fichier renvoyé par pipe(2)
. Je n'ai encore rien trouvé à ce sujet.
pipe()
appel du noyau avec la machinerie qui le prend en charge (pipefs
, etc.) est de niveau beaucoup plus bas que l'|
opérateur proposé dans votre shell. Ce dernier est généralement implémenté en utilisant le premier, mais ce n'est pas obligatoire.|
opérateur appelle simplementpipe(2)
comme un processus comme le fait bash.Réponses:
Jusqu'à présent, votre analyse est généralement correcte. La façon dont un shell peut définir le stdin d'un processus sur un descripteur de canal peut être (pseudocode):
la source
dup2
appel est nécessaire, et vous ne pouvez pas simplement assigner directement le descripteur de canal à stdin?pipe()
. L'dup2()
appel permet à l'appelant de copier le descripteur de fichier dans une valeur numérique spécifique (nécessaire car 0, 1, 2 sont stdin, stdout, stderr). C'est l'équivalent du noyau de "assigner directement à stdin". Notez que la variable globale de la bibliothèque d'exécution Cstdin
est aFILE *
, qui n'est pas liée au noyau (bien qu'elle soit initialisée pour être connectée au descripteur 0).dup2
appel ne change pasp[1]
. Au lieu de cela, il crée les deux poignéesp[1]
et0
pointe vers le même objet noyau (le tuyau). Étant donné que le processus enfant n'a pas besoin de deux poignées stdin (et ne saurait de toute façon quelle est la poignée numérotéep[1]
), ilp[1]
est fermé avantexec
.