Предположим, вы создали pipe
, а затем fork
. В родительском вас close
конец записи и fdopen
считывающий конец для получения FILE*
. В ребенке вы close
stdout
, dup2
конец записи трубы до stdout
, close
на обоих концах трубы и exec
. В каких условиях, например, что делает дочерний ребенок exec
d или какие-либо другие вызовы в родительском, родительский видит eof
на FILE*
, когда ребенок выйдет после потребления stdout
или вызовет как getline
?Разве родитель видит трубку eof при выходе из ребенка?
ответ
В стандартной библиотеке ввода-вывода используются read(2)
и write(2)
под капотом; поведение read(2)
заключается в возврате 0, чтобы указать EOF, когда в трубе больше нет данных и нет активных авторов (стандартная библиотека ввода-вывода затем преобразует это в отрицательную константу EOF, которую мы все знаем).
Итак, если вы правильно настроили, getline()
не будет висеть, и он вернется -1.
Если вы видите getline()
, висит, даже если ребенок закончил и закрыл трубу, вы, вероятно, оставили канал записи канала в другом месте. Двойная проверка, чтобы убедиться, что родитель закрыл канал записи перед вызовом getline()
.
Я считаю, что если вы правильно настроили трубку (и это похоже на вас), родитель должен действительно увидеть EOF. Связанная с этим проблема заключается в том, что родитель также должен заботиться о wait
для ребенка, иначе ребенок останется зомби.
Когда процесс прекращается по какой-либо причине, операционная система закрывает все оставшиеся дескрипторы открытых файлов.
Для труб, файлов и сокетов в ожидании данных сначала записывается/отправляется ОС. Другой одноранговый узел получает ожидающие данные, а затем EOF
, не требуется «правильная настройка».
Вы попробовали? –
@MartinJames Да, и я видел, как getline зависает после прочтения всего выхода ребенка. Поэтому я полагаю, что реальный вопрос заключается в том, при каких условиях родитель увидит фео. Я отредактирую вопрос. –
По общему признанию, без тестирования я бы предположил, что процесс чтения должен будет увидеть некоторое уведомление, иначе процесс 'grep' в' ls | grep somefilename' никогда не выйдет. –