а. Каково стандартное поведение, если процесс записи в канал убивается (т. Е. SIGKILL SIGINT) Он закрывает канал? Это промывает трубу? Или поведение не определено?
SIGKILL никогда не разрешает какую-либо очистку - процесс умирает, мертвый. С SIGINT это зависит от того, обрабатывает ли процесс сигнал. Если это так, он может выйти через exit (2), который очищает стандартные дескрипторы файла ввода / вывода. Вопрос в том - был ли канал подключен к стандартному выходу или через popen ()? Если это так, ожидающие буферизованные данные могут быть сброшены; если нет, то буферизованные данные отсутствуют, поэтому очистка не имеет значения.
Если в канале есть непрочитанные данные, эти данные остаются в канале, готовые для чтения ридером, при условии, что ридер есть.
б. Каково стандартное поведение, если процесс возвращается нормально? Гарантируется ли промывка трубы и ее закрытие? (конечно, без явного указания).
Это зависит от того, был ли канал подключен через стандартный ввод / вывод или нет. Если нет, то ничего не ожидается. Если это так, то да, любой материал в буферах будет очищен при закрытии стандартного потока ввода / вывода.
с. Спасибо за информацию о сигналах и непрочитанных данных, но меня немного смущает стандартное соединение каналов ввода / вывода. После того, как вы упомянули popen (), я посмотрел его, и страница man говорит, что его возвращаемое значение идентично потоку ввода-вывода, и потоки по умолчанию полностью буферизуются. Я просто не понимаю разницу между этими двумя понятиями, и при этом я не понимаю, откуда взялась разница.
Основной системный вызов для создания каналов - pipe(2)
. Он создает два файловых дескриптора, один для конца чтения канала, другой для конца записи. Если вы больше ничего с ними не делаете, они остаются как файловые дескрипторы с небуферизованным выводом (через write (2) и связанные системные вызовы). Если процесс завершается, в приложении нет буферизации; труба закрыта.
Если вы используете popen(3)
, то это сделает для вас гораздо больше работы. Он по-прежнему вызывает pipe(2)
для создания каналов, но затем выполняет fork(2)
. Дочерний организует правильную конфигурацию каналов и запускает дочерний процесс. Родитель также закрывает неиспользуемый конец канала и использует fdopen(3)
для создания стандартного потока файлов ввода / вывода для использования вызывающим процессом.
Если в файловом потоке есть данные в буфере ввода-вывода, то закрытие или эквивалент будет гарантировать, что ожидающие данные будут сброшены, а дескриптор файла закрыт.