2013-09-24 3 views
0

писать у меня есть это:поведения трубы Unix/Linux при чтении процесса прекращается до процесса

$ ls -lh file 
-rw-r--r-- 1 ankur root 181M Sep 23 20:09 file 

$ head -6 file 

z 
abc 
abc 
abc 
abc 
abc 

$ cat file | grep -m 1 z 
z 

Вопрос:

Почему cat командная строка в последней строке не умирает преждевременно SIGPIPE? Я думаю, что это должно произойти, потому что grep заканчивается в кратчайшие сроки по сравнению с cat file, что кошки 183 МБ файла. С исчезновением процесса чтения cat попытается написать разбитую трубу и должен умереть с SIGPIPE.

Update:

Я закончил тем, что писал это: readstdin.c

# include <unistd.h> 
# include <stdio.h> 

int main() { 

    ssize_t n ;   
    char a[5];   
    n = read(0, a, 3); 
    printf("read %zd bytes\n", n); 
    return(0); 

} 

Я использую это так:

$ cat file | ./readstdin 
$ yes | ./readstdin 

Но до сих пор cat или yes не умирает преждевременно. Я ожидаю, потому что процесс чтения заканчивается до того, как процесс записи будет выполнен.

+0

'Да' умирает, иначе он остался бы навсегда ... –

+2

Как сказал Базиле Старинкевич, процессы' cat' и 'yes' получают сигнал' SIGPIPE' и погибают. Статус выхода конвейера - это статус выхода финальной команды (т. Е. 'Grep'), поэтому, если более ранняя команда не работает, вы не увидите этого в статусе выхода. Почему вы думаете, что они не умирают преждевременно? –

+0

@AdamRosenfield Что заставляет вас думать, что они не умирают преждевременно, так это то, что я не вижу сообщение об ошибке, напечатанное на экране от 'cat' или' yes', они просто молча выходят. Но это может быть то, как они реализованы для обработки SIGPIPE. – abc

ответ

2

Если конец чтения некоторых pipe(2) является close(2) -ed, далее write(2) s получит SIGPIPEsignal(7). Читайте также pipe(7).

Они будут получать SIGPIPE при заполнении буфера трубы.

В команде yes | ./readstdin команда yes получает сигнал SIGPIPE. Просто попробуйте yes в терминале, он плюет на какой-то вывод бесконечно ad nauseam, пока вы его не убьете.

В команде cat file | ./readstdin, это может произойти (в частности, если file достаточно мал, меньше sysconf(_POSIX_PIPE_BUF) байт, которые могут быть 4096 байт), что команда cat является close(2) -ный STDOUT_FILENO дескриптора и что труба до сих пор не полный. Тогда cat может не получить SIGPIPE.

+0

См. Мое обновление к вопросу. Все идеи будут оценены. – abc

1

Нормальные процессы закрывают входной поток, вызывающий SIGPIPE. На странице руководства он упоминает, что -m прекращает чтение, и «обеспечивает, чтобы стандартный ввод был расположен сразу после последней соответствующей строки перед выходом». Таким образом, он фактически не закрывает поток. Вы можете продемонстрировать, как это:

cat file | (grep -m1 z && grep -m1 c) 

Вы получите первый c после первого z, что иногда бывает полезно. После того, как последний grep выйдет, потоку некуда идти, поэтому он остается непрочтенным, и вся группа команд выходит. Вы можете продемонстрировать:

(while true; do echo z; sleep 1; done) | grep -m3 z 
(while true; do echo z; sleep 1; done) | grep --line-buffered z | head -3 
+0

Что делать, если процесс чтения умирает (или выполняется) до завершения процесса записи? Что произойдет в этом случае? – abc

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