4. Tubes "anonymes" et tubes nommés

Revenons à l'exemple des tubes, car il est très intéressant et il constitue en soi une bonne illustration de la notion de liens. Lors de l'utilisation d'un tube dans une ligne de commande, le shell crée le tube et va faire en sorte que la commande située avant le tube écrive dans celui-ci, et que la commande située après lise les données du tube. Tous les tubes, qu'ils soient anonymes (comme ceux utilisés par le shell) ou nommés (voir ci-dessous), fonctionnent selon le principe FIFO (First In, First Out, soit « premier arrivé, premier servi »). Nous avons déjà vu des exemples sur comment utiliser les tubes avec le shell, mais regardons un autre exemple pour le bénéfice de notre démonstration :

$ ls -d /proc/[0-9] | head -5
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/

Ce qui ne peut se voir dans cet exemple (parce que cela se passe trop vite) est la chose suivante : les écritures sur le tube sont bloquantes. Cela veut dire que quand la commande ls écrit dans le tube, elle est bloquée jusqu'à ce qu'un processus à l'autre bout lise à partir du tube. Pour visualiser cet effet, on pourra créer des tubes nommés (et qui, donc, seront liés, par opposition aux tubes utilisés par le shell qui ne le sont pas)[7]. La commande pour créer de tels tubes est mkfifo :

$ mkfifo un_tube
$ ls -il
total 0
169 prw-rw-r--    1 reine    reine           0 déc 10 14:12 un_tube|
  #
  # On constate que le compteur de liens indique 1, et la sortie
  # que le fichier est un tube ('p').
  #
  # On pourra aussi utiliser ln ici :
  #
$ ln un_tube le_même_tube
$ ls -il
total 0
169 prw-rw-r--    2 reine    reine           0 déc 10 15:37 un_tube|
169 prw-rw-r--    2 reine    reine           0 déc 10 15:37 le_même_tube|
$ ls -d /proc/[0-9] >un_tube
  #
  # Le processus est bloqué puisqu'il n'y a pas de lecteurs à l'autre
  # bout. Tapez Control Z pour suspendre le processus...
  #
[1]+  Stopped                 ls -d /proc/[0-9] >a_pipe
  #
  # ... Puis placez-le en arrière-plan :
  #
$ bg
[1]+ ls -d /proc/[0-9] >a_pipe &
  #
  # Maintenant lisez depuis le tube...
  #
$ head -5 <le_même_tube
  #
  # ... le processus d'écriture se termine :
  #
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/
[1]+  Done                    ls -d /proc/[0-9] >a_pipe
$

De même, les lectures sont bloquantes. Si les commandes ci-dessus sont exécutées dans l'ordre inverse, nous observons que head se bloque en attendant qu'un processus lui envoie quelque chose à lire :

$ head -5 <un_tube
#
# Le processus est bloqué, suspendez-le : C-z
#
[1]+  Stopped                 head -5 <a_pipe
#
# Mettez-le en tâche de fond...
#
$ bg
[1]+ head -5 <a_pipe &
#
# ... Et donnez-lui à manger :)
#
$ ls -d /proc/[0-9] >le_même_tube
$ /proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/
[1]+  Done                    head -5 <un_tube
$

On constatera également un effet indésirable dans cet exemple : la commande ls a fini son exécution avant que la commande head ne prenne le relais. La conséquence est que vous êtes renvoyé immédiatement au prompt, et head n'est exécutée qu'après. Elle effectue en fait sa sortie seulement une fois le prompt récupéré.



[7] D'autres différences existent entre les deux types de tubes, mais cela sort du cadre de ce chapitre.