5.3. Tubes « anonymes  » et tubes nommés

Revenons à l'exemple des tubes, car il est très intéressant et c'est également une bonne illustration de la notion de liens. Quand vous utilisez un tube dans une ligne de commande, le shell crée le tube pour vous et fait en sorte que la commande avant le tube écrit dans celui-ci, tandis que la commande après le tube y lit ses données. Tous les tubes, qu'ils soient anonymes (comme ceux utilisés par le shell) ou nommés (voyez ci-dessous), fonctionnent selon le principe FIFO (First In, First Out, premier arrivé, premier servi). Nous avons déjà vu des exemples sur l'utilisation des tubes avec le shell, mais prenons-en un dans un but d'illustration :

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

Une chose que vous ne remarquez pas dans cet exemple (parce que cela se passe trop vite) est que 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 depuis le tube. Pour visualiser cet effet, vous pouvez créer des tubes nommés, qui, contrairement aux tubes utilisés par le shell, ont des noms (donc ils sont liés, tandis que les tubes utilisés par le shell ne le sont pas). La commande pour créer de tels tubes est mkfifo :

$ mkfifo un_tube
$ ls -il
total 0
    169 prw-rw-r--    1 fg       fg              0 déc 10 14:12 un_tube|
  #
  # Vous pouvez voir que le compteur de liens est 1, et que la sortie
  # montre  que le fichier est un tube ('p').
  #
  # Vous pouvez aussi utiliser ln ici :
  #
$ ln un_tube le_même_tube
$ ls -il
total 0
    169 prw-rw-r--    2 fg       fg              0 déc 10 15:37 un_tube|
    169 prw-rw-r--    2 fg       fg              0 déc 10 15:37 le_même_tube|
$ ls -d /proc/[0-9] >un_tube
  #
  # Le processus est bloqué, comme il n'y a pas de lecteurs à l'autre
  # bout. Tapez C-z pour suspendre le processus...
  #
zsh: 3452 suspended  ls -d /proc/[0-9] > un_tube
  #
  # ...Puis mettez-le en tâche de fond :
  #
$ bg 
[1]  + continued  ls -d /proc/[0-9] > un_tube
  #
  # Maintenant lisez depuis le tube...
  #
$ head -6 <le_même_tube
  # 
  # ...le processus écrivain se termine :
  #  
[1]  + 3452 done       ls -d /proc/[0-9] > un_tube
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/
$

De la même façon, les lectures sont bloquantes. Si nous exécutons les commandes ci-dessus dans l'ordre inverse, nous observons que head est bloqué, en attendant qu'un processus lui donne quelque chose à lire :

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

Vous pouvez aussi voir un effet indésirable dans cet exemple : la commande ls a fini son exécution avant que la commande head prenne le relais. La conséquence est que vous êtes retourné(e) au prompt immédiatement, mais head ne s'est exécuté qu'après. Donc il a effectué sa sortie seulement après que vous ayez récupéré le prompt :-)