Отправка данных из родительского процесса в дочерний и наоборот в C - PullRequest
3 голосов
/ 31 января 2010

Я создал программу, которая создает 5 каналов и 5 процессов в цикле. Мне удалось отправить данные из родительского процесса в каждый дочерний процесс, когда каждый дочерний процесс перекрывается другой программой. Каждый цикл выполняется следующим образом

( parent.c ):

// Child process - reads from pipe
if (childpid == 0) {
    dup2(fd[0], 0); // replace stdin with pipe input
    execv("program", arguments);

} else { // Parent process - writes to pipe
    write(fd[1], buffer, strlen(buffer)+1);
}

Так что теперь я могу получить данные, которые отправляются от родителя в канал, читая из STDIN_FILENO в программе, которую childs выполняет с execv (...).

Вот так ( program.c ):

char *buffer = (char *)malloc(50);
read(STDIN_FILENO, buffer, 50);

Однако моя проблема в том, как я могу отправить данные обратно родителю? Я думал о чем-то вроде замены stdout на трубу с помощью dup2 снова, но я не могу заставить его работать. Я понимаю, что это должно быть сделано до использования execv (...) по крайней мере.


Я не уверен, что этого объяснения было достаточно, чтобы я мог сделать небольшое изображение с текстом:)

Вот как сейчас:

  • Родитель -> Труба
  • Труба -> Дочерний процесс 1
  • Труба -> Дочерний процесс 2
  • Труба -> ...
  • Труба -> Дочерний процесс 5

Я хочу, чтобы это было так.

  • Родитель -> Труба
  • Труба -> Дочерний процесс 1
  • Труба -> Дочерний процесс 2
  • Труба -> ...
  • Труба -> Дочерний процесс 5
  • Дочерний процесс 1 -> Родительский
  • Дочерний процесс 2 -> Родительский
  • ...
  • Дочерний процесс 5 -> Родительский

Благодарю за помощь!

Ответы [ 4 ]

3 голосов
/ 31 января 2010

Трубы являются однонаправленными, а не двунаправленными, поэтому общим решением является создание еще пяти каналов (gak!) Для возвращаемых данных. Затем родитель должен использовать системный вызов select(), чтобы узнать, в каком из каналов возврата есть данные, готовые для чтения.

О, и я бы написал

    dup2(fd[0], 0); // replace stdin with pipe input
должно быть
    dup2(fd[0], 0); // replace stdin with output from pipe
и наоборот.

Как и в других ответах, есть другие способы общения, которые могут быть более подходящими, в зависимости от того, чего вы пытаетесь достичь.

2 голосов
/ 31 января 2010

См. Unix Program Faq здесь, посмотрите на вопрос 1,4 1,5 , возможно, с использованием карты памяти, чтобы родительские / дочерние процессы могли читать / писать с обоих концов ... Существует отличное руководство для понимания IPC здесь .

Редактировать: Спасибо Тренту за то, что он указал на небольшую ошибку в опечатке ... Я имел в виду 1,5 ...

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

0 голосов
/ 28 мая 2012

Если вы хотите продолжать использовать каналы, то создайте одну группу FD для связи потомка с родителями и одну для связи родителя с ребенком Поэтому вместо int fd [2] у вас есть int toParent [2], toChild [2]. Вместо dup2 (fd [0], 0) у вас есть dup2 (toChild [0], 0); dup2 (toParent [1], 1).

И не просто дублируйте, а закройте FD, которые вы не используете.

0 голосов
/ 31 января 2010

Я немного посмотрел в интернете. Кажется, что вы можете использовать каналы только для общения одним способом. Что имеет смысл - ввод из stdin и вывод в stdout. Если вы хотите иметь двустороннюю связь между вашими родительскими и дочерними процессами, используйте сокеты. Есть и другие способы достижения двухсторонней IPC. Я предлагаю вам больше узнать о межпроцессном взаимодействии.

Всего наилучшего.

...