Deux fenêtres, même utilisateur, avec des invites bash. Dans le type de fenêtre 1:
$ mkfifo f; exec <f
Donc bash tente maintenant de lire à partir du descripteur de fichier 0, qui est mappé sur le canal nommé f
. Dans le type de fenêtre 2:
$ echo ls > f
Maintenant, window-1 imprime un ls puis le shell meurt. Pourquoi?
Expérience suivante: ouvrez à nouveau la fenêtre-1 avec exec <f
. Dans le type de fenêtre 2:
$ exec 3>f
$ echo ls >&3
Après la première ligne ci-dessus, la fenêtre-1 se réveille et imprime une invite. Pourquoi? Après la deuxième ligne ci-dessus, window-1 imprime la ls
sortie et le shell reste vivant. Pourquoi? En fait, maintenant dans la fenêtre-2, echo ls > f
ne ferme pas le shell de la fenêtre-1.
La réponse doit avoir à voir avec l' existence du descripteur de fichier 3 de la fenêtre 2 référençant le canal nommé?!
la source
exec <f
,bash
on ne cherche pas à lire à partirf
, il est d' abord tenté d' ouvrir il. Leopen()
ne reviendra pas tant qu'il n'y aura pas de processus faisant une autre ouverture en mode écriture dans le tuyau (à quel moment le tuyau sera instancié et le shell lira les entrées de celui-ci).exec 3>f
exécuté, le premier shell donne ensuite une invite. (Point mineur, vouliez-vous dire "en mode écriture " dans votre commentaire?)Réponses:
Cela concerne la fermeture du descripteur de fichier.
Dans votre premier exemple,
echo
écrit dans son flux de sortie standard avec lequel le shell s'ouvre pour le connecterf
, et lorsqu'il se termine, son descripteur est fermé (par le shell). À la réception, le shell, qui lit les entrées de son flux d'entrée standard (connecté àf
), litls
, s'exécutels
puis se termine en raison de la fin du fichier sur son entrée standard.La condition de fin de fichier se produit car tous les rédacteurs du canal nommé (un seul dans cet exemple) ont fermé leur extrémité du canal.
Dans votre deuxième exemple,
exec 3>f
ouvre le descripteur de fichier 3 pour l'écrituref
, puis yecho
écritls
. C'est le shell qui a maintenant le descripteur de fichier ouvert, pas laecho
commande. Le descripteur reste ouvert jusqu'à ce que vous le fassiezexec 3>&-
. À la réception, le shell, qui lit les entrées de son flux d'entrée standard (connecté àf
), litls
, s'exécutels
puis attend plus d'entrée (car le flux est toujours ouvert).Le flux reste ouvert car tous les rédacteurs (shell, via
exec 3>f
etecho
) n'ont pas fermé leur extrémité du tube (exec 3>f
est toujours en vigueur).J'ai écrit plus
echo
haut comme s'il s'agissait d'une commande externe. Il est très probablement intégré à la coque. L'effet est néanmoins le même.la source
Il n'y a pas grand-chose: quand il n'y a pas d'écrivain dans le tube, il semble fermé aux lecteurs, c'est-à-dire qu'il retourne EOF à la lecture et se bloque à l'ouverture.
Depuis la page de manuel Linux (
pipe(7)
, mais voir aussififo(7)
):La fermeture de la fin d'écriture est ce qui se passe implicitement à la fin de la
echo ls >f
, et comme vous le dites, dans l'autre cas, le descripteur de fichier reste ouvert.la source
Après avoir lu les deux réponses de @Kusalananda et @ikkachu, je pense que je comprends. Dans la fenêtre 1, le shell attend quelque chose pour ouvrir l'extrémité d'écriture du tuyau, puis la fermer. Une fois l'écriture terminée, le shell de la fenêtre-1 affiche une invite. Une fois la fin de l'écriture fermée, le shell obtient l'EOF et meurt.
Du côté de la fenêtre 2, nous avons les deux situations décrites dans ma question: dans la première situation avec
echo ls > f
, il n'y a pas de descripteur de fichier 3, nous avons donc leecho
frai, et sonstdin
etstdout
ressemble à ceci:Puis se
echo
termine et le shell ferme les deux descripteurs. Étant donné que le descripteur de fichier 1 est fermé et fait référencef
, la fin d'écriture def
est fermée et cela provoque un EOF à window-1.Dans la deuxième situation, nous exécutons
exec 3>f
dans notre shell, ce qui oblige le shell à prendre cet environnement:Maintenant, nous exécutons
echo ls >& 3
et le shell alloue les descripteurs de fichiersecho
comme suit:Ensuite, le shell ferme les trois descripteurs ci-dessus, y compris
f
, mais af
toujours une référence à lui à partir du shell lui-même. C'est la différence importante. La fermeture du descripteur 3 avecexec 3>&-
fermerait la dernière référence ouverte et provoquerait un EOF à la fenêtre-1, comme l'a noté @Kusalananda.la source