Давайте повернемося назад до прикладу з каналами, оскільки він є досить цікавим, а також уявляє добру ілюстрацію для розуміння посилань. Коли ви в командному рядку використовуєте канал, 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 виконалася пізніше, і ви побачили її висновок тільки після повернення.