Я пытаюсь понять концепцию, включающую команды 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
C1
dup2()
с стандартом до конца записи изpipe1
C1
закрыть с обоих концовpipe1
(потому что мы одураченных его уже)C1
execvp()
сек программа ('кто')
C2:
C2
dup2()
прочитаем конецpipe1
кstdin
так что он получает вход для программы, которая будет выполненаC2
закрывает оба концаpipe1
C2
ждет ввода наstdin
изC1
отdup
редpipe1
C2
execvp()
сек Программа ('рода') с этим входом
Теперь, если бы я это сделать, как описано выше, мне не повезло бы. Однако, если я ввел еще одну трубу
pipe2
это выглядит примерно так:
P:
P
закрывает как концов ненужных трубpipe2
P
закрывает ненужный конец считыванияpipe1
P
отправляет аргумент программы ('who') вC1
черезpipe1
P
закрывает написать КОНЕЦP
ждет для детей, чтобы выйти из
C1:
C1
закрывает читать конецpipe2
C1
читает аргумент от конца чтения отpipe1
C1
dup2()
S стандарт до конца записи вpipe2
C1
закрывает написать конецpipe2
C1
закрывает оба концаpipe1
- сpipe2
,pipe1
резервированной в этом ребенкеC1
execvp()
ВЛЯЕТСЯ программы («кто»)
C2:
C2
dup2()
прочитаем конецpipe2
кstdin
C2
закрывает оба концаpipe1
C2
ожидает ввода наstdin
изC1
отdup
редpipe2
C2
выполняет программуsort
с этим ввод
Является ли предположение правильным, что трубы не должны повторно использоваться в нескольких процессах, потому что система может быть не уверена, кому «служить»? Или есть еще одна причина для этого?
Можете ли вы подробнее рассказать? Правильно ли я понимаю ситуацию: P как-то получает вход, подобный 'a | b', затем создает C1 и C2, C1, выполняющие a, C2, выполняющие b. a stdout должен быть stdin. Я прав? Это требование? Не может P только вилка C1, а C1 может вилка C2? – holgac
Кроме того, семейство 'exec' не продолжается после указанной операции, поэтому C1 и C2 завершатся после команд. Это означает, что всякий раз, когда P получает новый вход, такой как 'a | b', он снова будет вилкой. Так как это так, связь между P и C1 и P и C2 представляется избыточной здесь. – holgac
@holgac Да, вы совершенно правы. Это требование. Я бы знал, как это сделать, как вы это заявили. –