Трубы между дочерними процессами в C - PullRequest
1 голос
/ 25 июля 2011

Я уже видел этот вопрос раньше, но все еще немного сбит с толку: как мне создать связь между дочерними процессами одного и того же родителя? Все, что я сейчас пытаюсь сделать, это передать сообщение от первого дочернего процесса к n-му дочернему процессу. Моя идея состоит в том, чтобы создать n-1 конвейеры в родительском процессе, а затем перенаправить концы родительского процесса в следующий дочерний процесс. Что я не могу понять, так это как бы мы перенаправили концы из родительского, если следующий дочерний процесс не был создан? Я чувствую, что есть проблема в том, как я к этому подхожу.

РЕДАКТИРОВАТЬ: Моя цель - напечатать сообщение, которое было передано от первого дочернего процесса к последнему. Это простая программа.

Ответы [ 4 ]

1 голос
/ 25 июля 2011

Вам не нужно сначала создавать процессы.Решение заключается в следующем: вы сначала создаете все необходимые каналы, сохраняете их в некотором массиве.Затем вы делаете fork, перенаправляете входной и выходной потоки (для дочернего процесса) соответственно, закрываете неиспользуемые концы канала и выполняете exec.Каналы могут существовать без соответствующих процессов, у них есть буферы, поэтому вы можете писать в канал, пока никто еще не читает, все будет в порядке.

Вы должны просто знать о закрытии неиспользуемых идентификаторов перед выполнением exec.И будьте внимательны при записи в канал, в котором входные конечные точки (все входные конечные точки) могут закрыться: это может привести к SIGPIPE.

0 голосов
/ 25 июля 2011

В упрощенном, не exec случае, вы должны сделать что-то вроде.

#define nproc 17

int pipes[nproc - 1][2];
int pids[nproc];

int i;
for( i = 0; i < nproc - 1; i++ ) {
    pipe( pipes[i] );
}

int rank;
for( rank = 0; rank < nproc; rank++ ) {
    pids[rank] = fork();
    if( !pids[rank] ) {
        if( rank == 0 ) {
            write( pipe[rank][1], /* your message */ );
        }

        read( pipe[rank-1][0], /* read the message somewhere*/ );

        if( rank < nproc - 1 ) {
            write( pipe[rank][1], /* write the message to the next child process*/ );
        } else {
            // Here print the received message (it's already received above)
        }
    }
}

for( rank = 0; rank < nproc; ++rank ) {
    wait( pids[rank] );
}
0 голосов
/ 25 июля 2011

Вместо того, чтобы использовать неназванные каналы, вы можете рассмотреть альтернативный механизм для межпроцессного взаимодействия, такой как использование FIFO, очереди сообщений или сокета с использованием дейтаграмм (то есть UDP), который позволил бы вамзаписать «сообщение» в коммуникационный буфер, а затем попросить другого потомка прочитать сообщение, посмотреть, не предназначено ли оно для них, а если нет, попросить его поместить его обратно в буфер связи, чтобы другой дочерний элемент мог его прочитать.В противном случае, если сообщение предназначено для них, они принимают его.

Ваше сообщение может быть struct, которое содержит идентификатор отправителя, идентификатор получателя, а затем некоторый буфер для хранения сообщения, будь то строковый тип и т. Д.

Буфер связиможет быть установлен родителем и унаследован детьми.

0 голосов
/ 25 июля 2011

Код для настройки канала и перенаправления stadin / stdout на канал.

В родительской (перед вилкой)

   int p[2];
   pipe(p);

у ребенка (после развилки) получить трубу как стандартный

   close(0);
   dup(p[0]);

У ребенка (после развилки) получить трубу как стандартный вывод

  close(1);
  dup(p[1]);

Вы можете начать запись в канал, как только он будет создан. Однако этот дочерний процесс, который записывает в канал, приостанавливается, как только буфер канала заполняется, и до тех пор, пока другой процесс не начнет чтение из канала.

Также посмотрите на открытый вызов , поскольку это может быть более простой версией того, что вам нужно.

...