Давайте вернемся назад к примеру с
каналами, поскольку он весьма интересен, а
также является хорошей иллюстрацией для
понимания ссылок. Когда вы в командной
строке используете канал, 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: # # You can also use ln here: # $ 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] Существуют и другие различия между этими двумя типами каналов, но это выходит за рамки данной книги.