4. “Анонімні” канали та іменовані канали

Давайте повернемося назад до прикладу з каналами, оскільки він є досить цікавим, а також уявляє добру ілюстрацію для розуміння посилань. Коли ви в командному рядку використовуєте канал, shell створює для вас канал і працює так, що команда перед каналом виконує в нього запис, а команда після каналу виконує читання з нього. Усе канали, чи то анонімні (як ті, що використовуються в shell'ах), чи то іменовані (дивіться нижче), працюють відповідно до принципу простої черги FIFO (First In, First Out, “першим прийшов - першим обслуговано”). Ми вже бачили приклади використання каналів в shell'і, але погляньмо ще на один приклад для демонстрації цього принципу:

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

Одна річ, яку ви не помітите в цьому прикладі (бо це відбувається занадто швидко), полягає в блокуванні запису в канали. Це означає, що коли команда ls виконує запис в канал, він блокується доти, доки процес виконує читання на іншому кінці. Щоб побачити цей ефект, ви можете створити іменовані канали, які, на відміну від каналів, використовуваних shell'ами, мають імена (тобто вони є пов'язаними, тоді як канали shell'а - ні)[5]. Команда для створення іменованого каналу - mkfifo:

$ mkfifo a_pipe
$ ls -il
total 0
169 prw-rw-r--  1 queen queen 0 Aug  6 19:37 a_pipe|
  #
  #Ви можете бачити, що лічильник посилань дорівнює 1,
  # а файл є каналом ('p').
  #
  # Ви також можете використовувати тут ln:
  #
$ ln a_pipe the_same_pipe
$ ls -il
total 0
169 prw-rw-r--  2 queen queen 0 Aug  6 19:37 a_pipe|
169 prw-rw-r--  2 queen queen 0 Aug  6 19:37 the_same_pipe|
$ ls -d /proc/[0-9] >a_pipe
  #
  # Процес заблоковано, бо на іншому кінці немає програми читання.
  # Натисніть Control Z, щоб призупинити процес...
  #
[1]+  Stopped                 ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe
  #
  # ...Потім відправте його у фоновий режим:
  #
$ bg
[1]+ ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe &
  #
  # тепер виконуємо читання з каналу...
  #
$ head -5 <the_same_pipe
  #
  # ...процес запису завершено
  #
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/
[1]+  Done                    ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe
$

Аналогічним чином читання теж блокується. Якщо ми виконаємо наведені вище команди у зворотному порядку, ми побачимо що команда head блокується, очікуючи, щоб якийсь процес дав їй щось прочитати:

$ head -5 <a_pipe 
# 
# Програму заблоковано, призупиніть її: C-z 
# 
[1]+  Stopped                 head -5 <a_pipe 
# 
# Відправляємо її в фоновий режим...  
# 
$ bg 
[1]+ head -5 <a_pipe &
# 
# ...І даємо їй щось поїсти :) 
# 
$ ls -d /proc/[0-9] >the_same_pipe 
/proc/1/ 
/proc/2/ 
/proc/3/ 
/proc/4/ 
/proc/5/ 
[1]+  Done                    head -5 <a_pipe
$

Ви також можете побачити небажаний ефект у попередньому прикладі: команду було ls завершено до того, як почала працювати команда head. У результаті ви негайно повернулися до запрошення в консолі, а head виконалася пізніше, і ви побачили її висновок тільки після повернення.



[5] Існують інші відмінності між цими двома типами каналів, але це виходить за рамки цієї книги.