параллельная вилка трубы - PullRequest
       36

параллельная вилка трубы

0 голосов
/ 04 февраля 2011
void doWork(){

  int fd[2];
  int pret = pipe(fd);

  close(0);
  close(1);
  int dret = dup2(fd[1], 1);
  close(fd[1]);

  while(1){

    char buf[256];
    system("whoami");
    int rret = read(fd[0], buf, 256);

    if(/* something interesting */){
      return;
    }
  }
}

int main(int argc, char* argv[]){

  int children = 2;

  for(unsigned work = 0; work < children; ++work){

    pid_t pid = fork();

    if(pid == 0){
      doWork();
      break;
    }
  }
  int status;
  wait(&status);

  return 0;
}

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

РЕДАКТИРОВАТЬ: я пытаюсь добиться параллелизма задач с помощью fork / pipe.Нет связи между родительским и дочерним процессами.Каждый дочерний процесс выполняет внешнюю программу, читает выходные данные, обрабатывает выходные данные и продолжает работу до тех пор, пока не будет найден желаемый выходной результат.

Ответы [ 3 ]

6 голосов
/ 04 февраля 2011

Вам нужно создать трубу до fork(), а не после. В вашем коде только дочерний процесс будет иметь канал. Вам нужны оба процесса, чтобы поделиться им.

Например: *. * 1004

int fd[2];
pid_t pid;

if (pipe(fd)) { /* TODO: handle error */ }

pid = fork();
if (pid < 0) { /* TODO: handle error */ }

if (pid == 0)
{
   /* We are the child.  Set fd[1] as stdout. */
   if (dup2(fd[1], 1)) { /* TODO: handle error */ }

   /* Close fd[0]; this process doesn't need it. */
   close(fd[0]);

   do_work();
   exit(0);
} 
else
{
   /* We are the parent... */
   /* Close the other guy's write fd. */
   close(fd[1]);

   /* Now read from fd[0] */
   /* Possibly waitpid() on child pid, etc. */
}

Также: мне нравится звонить fflush(stdout); до того, как я fork(). В противном случае вы будете наблюдать странное поведение с printf().

1 голос
/ 04 февраля 2011

Вы хотите порождать дочерний процесс, который затем выполняет некоторый подпроцесс, анализирует его содержимое, интерпретирует его и затем завершает работу?Если это так, вам нужно fork дважды для каждой задачи, которую вы хотите создать.Первый раз для создания дочернего элемента, который будет обрабатывать результат подпроцесса, второй раз для запуска подпроцесса.

Примерно так:

void ExecuteCommandAndInterpretResult(const char* command)
{
    int fd[2];
    if (pipe(fd))
        exit(1);

    pid_t pid = fork();
    if (pid < 0)
        exit(1);

    if (pid == 0)
    {
        if (dup2(fd[1], 1))
            exit(1);

        close(fd[0]);
        execl(command, basename(command), NULL);
        exit(1);
    }
    else
    {
        int status;

        close(fd[1]);
        // do something with output from command

        wait(&status);
        exit(0);
    }
}

#define CHILDREN 2
int main()
{
    unsigned int i;
    pid_t pids[CHILDREN];

    for (i = 0; i < CHILDREN; i ++)
    {
        pids[i] = fork();
        if (pids[i] < 0)
        {
            // TODO: handle error
        }
        else if (pids[i] == 0)
        {
            ExecuteCommandAndInterpretResult("/usr/bin/ls");
            exit(0);
        }
    }

    for (i = 0; i < CHILDREN; i ++)
    {
        if (pids[i] > 0)
        {
            int status;
            waitpid(pids[0], &status, 0);
        }
    }

    return 0;
}
0 голосов
/ 05 февраля 2011

Рассматривали ли вы использование popen() в ребенке для выполнения whoami?

...