У меня есть две простые программы: A
и B
. A
запускается первым, затем B
получает «стандартный вывод» A
и использует его в качестве «стандартного ввода». Предположим, я использую операционную систему GNU / Linux, и самый простой способ сделать это будет:
./A | ./B
Если бы мне пришлось описать эту команду, я бы сказал, что это команда, которая принимает входные данные (то есть читает) от производителя ( A
) и записывает в потребителя ( B
). Это правильное описание? Я что-то пропустил?
pipe
terminology
nihulus
источник
источник
Ответы:
Единственное, что в вашем вопросе является неправильным, так это то, что вы говорите
Фактически обе программы будут запущены практически одновременно. Если нет ввода для того,
B
когда он пытается прочитать, он будет блокироваться до тех пор, пока нет ввода для чтения. Аналогично, если никто не читает выходные данныеA
, их записи будут блокироваться до тех пор, пока их выходные данные не будут прочитаны (некоторые из них будут буферизованы каналом).Единственное, что синхронизирует процессы, участвующие в конвейере, - это ввод-вывод, то есть чтение и запись по конвейеру. Если не происходит запись или чтение, тогда эти два процесса будут работать независимо друг от друга. Если один из них игнорирует чтение или запись другого, игнорируемый процесс блокируется и, в конечном счете, прерывается
SIGPIPE
сигналом (при записи) или получает условие конца файла в своем стандартном входном потоке (при чтении), когда другой процесс завершается ,Идиоматический способ описать
A | B
это то, что это конвейер, содержащий две программы. Выходные данные, полученные на стандартном выходе первой программы, доступны для чтения на стандартном входе второй («[выходные данные]A
передаются на [входные данные]B
»). Оболочка выполняет необходимые сантехнические работы, чтобы это произошло.Если вы хотите использовать слова «потребитель» и «производитель», я думаю, это тоже нормально.
Тот факт, что это программы, написанные на C, не имеет значения. Тот факт, что это Linux, macOS, OpenBSD или AIX, не имеет значения.
источник
mkfifo
для создания именованного канала, затем запустить B в фоновом режиме чтения из канала, а затем A записать в него. Хотя это и есть придирки, так как эффект будет таким же.yes | sed 10q
Термин, обычно используемый в документации, - это «конвейер», который состоит из одной или нескольких команд, см. Определение POSIX. Так что с технической точки зрения это две команды, которые у вас есть, два подпроцесса для оболочки (либо
fork()+exec()
внешние команды, либо подоболочки)Что касается части производитель-потребитель , конвейер может быть описан этим шаблоном, так как:
/proc/<pid>/fd
каталог).stdout
а потребители читают,stdin
как если бы они выполняли одну команду, то есть они могут существовать друг без друга .Различие, которое я вижу здесь, состоит в том, что в отличие от Producer-Consumer в других языках команды оболочки используют буферизацию и записывают стандартный вывод после заполнения буфера, но нет упоминания о том, что Producer-Consumer должен следовать этому правилу - только ждать, когда очередь заполнена или отменена данные (что еще не делает конвейер).
источник