2015-04-24 6 views
1

Я пытаюсь понять концепцию, включающую команды dup2(), exec() и трубы в соединении.Путаница с dup2(), exec() и трубами

То, что я пытаюсь достичь:

трубы на выходе из программы X на вход программы Y.

Что-то вроде основного who | sort

с родительский и дети, в которых дети несут ответственность за выполнение программ, а родитель, передающий программы, дети.

Вот что я не понимаю, о трубах:

P1) Трубы трактуются как файлы и должны быть в одном направлении, но что мешает мне использовать одну трубу для нескольких однонаправленных каналов связи? Итак, допустим, что у меня есть pipe1 и три процесса (P - parent - C1, C2, дети), у которых есть труба, открытая форкировкой. Все эти процессы используют дескрипторы файлов. Предположим, что мы делаем все правильно, закрывая неиспользованные концы труб, P теперь пишет что-то C1. В чем проблема с использованием трубы для связи между C1 и C2? Как раз во время написания этого вопроса мне удалась идея: есть ли проблема с тем, кто читает ее, хотя многие процессы могут открывать ее одновременно (два процесса блокируют чтение), то есть система не может точно сказать, кто хочет читать записанные в буфер данные? Если да, то как это реализовано в системе?

Я действительно пытаюсь понять концепцию, поэтому, пожалуйста, несите меня.

Чтобы применить этот вопрос в реальную жизнь здесь некоторый псевдокод я имею дело с:

P:

  • P закрывает ненужный конец считывания pipe1
  • P Посылает аргумент программы (» кто ') до C1 через pipe1
  • P закрывает запись конец
  • P ждет для детей, чтобы выйти из

С1:

  • C1 считывает аргумент из конца чтения pipe1
  • C1dup2() с стандартом до конца записи из pipe1
  • C1 закрыть с обоих концов pipe1 (потому что мы одураченных его уже)
  • C1execvp() сек программа ('кто')

C2:

  • C2dup2() прочитаем конец pipe1 к stdin так что он получает вход для программы, которая будет выполнена
  • C2 закрывает оба конца pipe1
  • C2 ждет ввода на stdin из C1 от dup ред pipe1
  • C2execvp() сек Программа ('рода') с этим входом


Теперь, если бы я это сделать, как описано выше, мне не повезло бы. Однако, если я ввел еще одну трубу pipe2 это выглядит примерно так:
P:

  • P закрывает как концов ненужных труб pipe2
  • P закрывает ненужный конец считывания pipe1
  • P отправляет аргумент программы ('who') в C1 через pipe1
  • P закрывает написать КОНЕЦ
  • P ждет для детей, чтобы выйти из

C1:

  • C1 закрывает читать конец pipe2
  • C1 читает аргумент от конца чтения от pipe1
  • C1dup2() S стандарт до конца записи в pipe2
  • C1 закрывает написать конец pipe2
  • C1 закрывает оба конца pipe1 - с pipe2, pipe1 резервированной в этом ребенке
  • C1execvp() ВЛЯЕТСЯ программы («кто»)

C2:

  • C2dup2() прочитаем конец pipe2 к stdin
  • C2 закрывает оба конца pipe1
  • C2 ожидает ввода на stdin из C1 от dup ред pipe2
  • C2 выполняет программу sort с этим ввод

Является ли предположение правильным, что трубы не должны повторно использоваться в нескольких процессах, потому что система может быть не уверена, кому «служить»? Или есть еще одна причина для этого?

+0

Можете ли вы подробнее рассказать? Правильно ли я понимаю ситуацию: P как-то получает вход, подобный 'a | b', затем создает C1 и C2, C1, выполняющие a, C2, выполняющие b. a stdout должен быть stdin. Я прав? Это требование? Не может P только вилка C1, а C1 может вилка C2? – holgac

+0

Кроме того, семейство 'exec' не продолжается после указанной операции, поэтому C1 и C2 завершатся после команд. Это означает, что всякий раз, когда P получает новый вход, такой как 'a | b', он снова будет вилкой. Так как это так, связь между P и C1 и P и C2 представляется избыточной здесь. – holgac

+0

@holgac Да, вы совершенно правы. Это требование. Я бы знал, как это сделать, как вы это заявили. –

ответ

2

Трубы предназначены в первую очередь для индивидуального общения - один писатель, один читатель. Хотя нет ничего, что мешает имея столько читателей и писателей, как вы хотите, поведение часто делает это не очень полезная, особенно с несколькими читателей:

  • Чтение из трубы является необратимой операцией: каждый посланный байт через труба будет прочитана ровно одним из читателей, кто бы ни захватил ее первым.Если вы хотите транслировать некоторую информацию, вам нужно либо использовать другой механизм IPC, либо явно реплицировать данные (например, команду tee).
  • Если существует несколько авторов, их записи чередуются несколько непредсказуемым образом. Единственная гарантия заключается в том, что записи размером PIPE_BUF или менее являются атомарными.
  • Если число писателей падает до нуля, читатель видит условие конца файла.

В архитектуре вы описываете, то есть два независимых канала связи: Р посылает who к C1, и C1 посылает выходной сигнал запуска команды who к C2. В сценарии оболочки, что будет что-то похожее на

echo who | { read command; exec command; } | sort 

с echo who, выполненной в оригинальном процессе, а не в субоболочке.

Ваше первое предложение не работает, потому что нет способа сказать, что выход P будет идти в C1, а выход C1 перейдет к C2. Это по-прежнему одна и та же труба, поэтому выход P может перейти на C2, а выход C1 может вернуться к самому себе, или это может быть смесь.

+0

Хорошо, спасибо, поэтому вы в основном подтверждаете, что я до сих пор принимал. Это определенно имеет смысл, зная, что трубы используются для связи 1 на 1 по указанным причинам. –

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

  • Нет связанных вопросов^_^