Основные вопросы о Трубах
Вопрос
У меня есть несколько основных вопросов о трубах, в которых я не уверен.
а) Каково стандартное поведение, если процесс, записывающий в канал, прерывается (т.е.SIGKILL SIGINT) Закрывает ли это канал?Промывает ли это трубу?Или поведение не определено?
б) Каково стандартное поведение, если процесс возвращается нормально?Гарантировано ли промывание трубы и ее закрытие?(конечно, не делая этого явно).
Я бы хотел, чтобы эти ответы были как можно более общими, но на самом деле, если это полностью зависит от спецификаций операционной системы, я могу с этим согласиться!Однако, если существует стандарт Posix или текущее определенное поведение Windows, я был бы очень признателен узнать.
Спасибо.
Решение
a.Каково стандартное поведение, если процесс, записывающий в канал, прерывается (т.е.SIGKILL SIGINT) Закрывает ли это канал?Промывает ли это трубу?Или поведение не определено?
SIGKILL никогда не допускает никакой очистки - процесс умирает, мертвый.С SIGINT это зависит от того, обрабатывает ли процесс сигнал.Если это так, то, скорее всего, он завершится через exit(2), который сбрасывает стандартные дескрипторы файлов ввода-вывода.Вопрос в том, был ли канал подключен к стандартному выводу или через popen()?Если да, то выдающиеся буферизованные данные мочь быть покрасневшим;если нет, то буферизованные данные отсутствуют, поэтому очистка несущественна.
Если в канале есть непрочитанные данные, эти данные остаются в канале, готовые к сбору считывателем - при условии, что считыватель есть.
b.Каково стандартное поведение, если процесс возвращается нормально?Гарантировано ли промывание трубы и ее закрытие?(конечно, не делая этого явно).
Это зависит от того, был ли канал подключен через стандартный ввод-вывод или нет.Если нет, то на рассмотрении ничего нет.Если это так, то да, любой материал в буферах будет удален при закрытии стандартного потока ввода-вывода.
c.Спасибо за информацию о сигналах и непрочитанных данных, но меня немного смущает стандартное подключение к каналу ввода-вывода.После того, как вы упомянули popen() Я просмотрел его, и на справочной странице указано, что возвращаемое значение идентично потоку ввода-вывода, и потоки по умолчанию полностью буферизованы.Мне просто не совсем ясно, в чем разница между этими двумя, и я не понимаю, откуда берется эта разница.
Основным системным вызовом для создания каналов является pipe(2)
.Он создает два файловых дескриптора, один для конца чтения канала, другой для конца записи.Если вы больше ничего с ними не делаете, то они остаются в виде файловых дескрипторов с небуферизованным выводом (через write(2) и связанные системные вызовы).Если процесс завершается, буферизация в приложении отсутствует;труба закрыта.
Если вы используете popen(3)
, тогда это сделает для вас намного больше работы.Это все еще вызывает pipe(2)
для создания каналов, но затем он выполняет fork(2)
.Дочерний процесс настраивает правильную конфигурацию каналов и запускает дочерний процесс.Родительский элемент также закрывает неиспользуемый конец канала и использует fdopen(3)
создать стандартный поток файлов ввода-вывода для использования вызывающим процессом.
В случае с файловым потоком, если в буфере ввода-вывода есть данные, то закрытие или эквивалент гарантирует удаление оставшихся данных и закрытие файлового дескриптора.
Другие советы
Нормальное поведение заключается в том, что все файловые дескрипторы закрываются при завершении процесса.Это означает, что канал, как и любой другой открытый файловый дескриптор, обычно закрывается.
Однако есть одна интересная вещь о трубах:в POSIX, если процесс выполняет запись в канал, который был закрыт, записывающее устройство получит сигнал SIGPIPE.
Редактировать:
Предостережение:Разница между завершением SIGx и обычным завершением заключается в том, что, как и при любой другой записи в файл, вы можете потерять данные, которые были буферизованы (посредством записи в файл) и еще не записаны в файловый дескриптор.