ОК, диаграмма:
initially: parent process: has
B_TO_A[0] and [1] open,
has A_TO_B[0] and [1] open
fork (makes copy)
parent: child (pid==0):
B_TO_A both open, A_TO_B both open call process_A: close unwanted pipe ends, loop
call wait(), wait for one child loop reads stdin, writes one pipe, reads other pipe
if we ever get here:
fork (makes copy)
parent: child (pid==0):
B_TO_A both open, A_TO_B both open call process_B: close unwanted pipe ends, loop
parent: both ends of both pipes open
call wait(), wait for one child loop reads one pipe, writes other pipe
Во-первых, вы обычно не доберетесь до «если мы когда-нибудь попадем сюда», потому что дочерний элемент, работающий с process_A()
, работает в цикле до тех пор, пока либо EOF на stdin (если этопроисходит первым) или один из вызовов чтения / записи канала завершается неудачно (например, из-за EOF на input_pipe[0]
).Поскольку родительский объект все еще ожидает вызова wait (), и оба конца обоих каналов открыты, EOF в канале (EOF в канале возникает после того, как вы прочитали все данные, записанные всеми авторами, и все dup
с конца записи были закрыты).Таким образом, единственный способ добиться этого - нажать EOF на stdin, чтобы цикл while
не запускался.
Во-вторых, если вам удастся снова разветвляться и делать process_B()
, этот ребенок будеттакже ждите вечно, потому что один конец записи канала, из которого он читает, все еще открыт ... в родительском!Родитель не закроет его, потому что родитель будет ждать вечно в wait
.
В общем, что вам нужно сделать здесь:
- создать два канала (как вы делаете сейчас)
- fork один раз, и запустите
process_A()
в дочернем - fork снова (в родительском), и запустите
process_B()
в (новом) дочернем - закрыть оба конца обоих каналов (в родительском элементе)
- дождаться обоих потомков, после оба запустились
Обрабатывается ошибканемного грязно, так как вы должны что-то сделать (например, kill()
первый ребенок), если вы не можете запустить второго ребенка.Так что вам нужно знать, как далеко вы продвинулись.Вы по-прежнему можете выполнять цикл с разветвлением дважды, но вы не можете wait
внутри цикла, и всего за два обхода цикла, каждый из которых выполняет довольно разные шаги, вы можете просто записать все это без цикла.