2014-01-25 2 views
6

Почему не yes | head повесить?Почему «да» голова не висит?

Я думал, что система собирает весь результат от yes, а затем передает его на head, а потому, что yes - бесконечный цикл, система зависает. Но он может фактически остановиться и показать 10 строк y.

Как система может остановить yes, когда head сделан сбор данных?

+0

возможно дубликат [Bash с трóбами] (http://stackoverflow.com/questions/19122/bash-pipe-handling) – devnull

+0

Также см [это] (http://stackoverflow.com/questions/10031344/why-is-this-pipe-terminated). – devnull

+0

Если вам действительно нужно его повесить, используйте 'yes | tail'. :-) –

ответ

5

Когда вы говорите yes | head оболочка будет устраивать такие вещи, что выход yes идет к pipe и вход head происходит от той же трубы. Когда head считывает 10 строк, он закрывает свой STDIN_FILENO, тем самым закрывая его конец. Когда yes пытается записать в закрытый канал, он получает SIGPIPE, действие по умолчанию которого должно его убить.

Простой способ проверить это с strace:

$ strace yes | head 
y 
[...] 
y 
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe) 
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=4069, si_uid=1000} --- 
+++ killed by SIGPIPE +++ 
+0

Опция '-f' ничего не помогает. Это похоже на попытку проследить как «да», так и «голова», но это не так, потому что 'strace' не является специальной оболочкой, которая может видеть весь конвейер. –

+0

@ WumpusQ.Wumbley Я не собирался отслеживать оба; 'strace -f' - это просто рефлекс, который я поднял. Я удалил его, хороший звонок :-) – cnicutar

4

система собирает все результат от да и то трубы его голову

Это было бы крайне неэффективно. Когда вы используете канал, операционная система создает буфер для связи с каналом.

send | receive 

Пока есть достаточно места в буфере процесс отправки будет писать в нем, и если есть достаточное количество данных в буфере, приемник будет обрабатывать его. Если процесс ожидания не заблокирован.

Как только head заканчивается, ОС уведомляет, что он завершен, он вызовет сигнал (SIGPIPE), который завершит процесс отправки (если процесс не обработает его).

+2

Последний абзац отрывочный. ОС не посылает сигнал «как только заканчивается». Скорее, когда головка заканчивается, ОС закрывает прочитанную сторону трубы. Когда «да» перенесено, он (в конце концов) попытается записать в трубу, после чего сигнал будет поднят. Рассмотрим разницу между 'yes>/dev/null | true' и 'yes | true'. –

Смежные вопросы