Создайте дочерний элемент, используя fork() внутри цикла for, чтобы запустить execlp() с двумя каналами, используя dup

Я пишу программу C, которая будет запускать команды Linux, например:

$ кошка /etc/passwd | вырезать -f1 -d: | Сортировать

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

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>

int main()
{
  int i,fd1[2],fd2[2],status,listpid[3];
  pid_t child;
  pipe(fd1);
  pipe(fd2);

  for(i=0; i< 3; i++)
  {
    printf("\ncreating child\n");
    if((child = fork()) == -1)
    {
      perror("fork");
      exit(EXIT_FAILURE);

    }
    else if(child == 0)
    {
      if(i == 0)
      {
    close(1); dup(fd1[1]);
    close(fd1[0]);
    close(fd1[1]);
    printf("\nrunning cat /etc/passwd\n");
    fflush(stdout);
    execlp("cat","cat","/etc/passwd", (char *)NULL);
    exit(EXIT_SUCCESS);

      }
      else if(i == 1)
      {
    close(0); dup(fd1[0]);
    close(fd1[1]);
    close(fd1[0]);
    close(1); dup(fd2[1]);
    close(fd2[1]);
    close(fd2[0]);
    printf("\nrunning cut -f1 -d:\n");
    fflush(stdout);
    execlp("cut","cut","-f1","-d:", (char *)NULL);
    exit(EXIT_SUCCESS);

      }
      else if(i == 2)
      {
    close(0); dup(fd2[0]);
    close(fd2[1]);
    close(fd2[0]);
    close(fd1[0]);
close(fd1[1]);
    printf("\nrunning sort\n");
    fflush(stdout);
    execlp("sort","sort", (char *)NULL);
    exit(EXIT_SUCCESS);

      }

    }
    else
    {
      listpid[i]=child;
    }

  }

  close(fd1[0]);
  close(fd1[1]);
  close(fd2[0]);
  close(fd2[1]);

  for(i = 0; i < 2; i++) 
  {
    waitpid(listpid[i], &status, 0);

    if(WIFEXITED(status)) 
    {
      printf("\n[%d] TERMINATED (Status: %d)\n",listpid[i], WEXITSTATUS(status));

    }

  }
  exit(EXIT_SUCCESS);

}

person user1863673    schedule 30.11.2012    source источник


Ответы (2)


Вам нужно закрыть канал fd1 в дочернем элементе 2, иначе дочерний элемент 1 будет зависать в ожидании большего количества возможных входных данных.

Еще одна проблема: цикл waitpid должен иметь условие цикла i < 3, а не i < 2.

person ecatmur    schedule 30.11.2012

Причина, по которой он «зависает», заключается в том, что sort ожидает ввода дополнительных данных. Он не будет ничего выводить, пока входные каналы не будут закрыты. Возможно что-то не так с вашими каналами (вы должны проверить возвращаемые значения из pipe и dup), но я ничего не вижу.

Я предполагаю, что cut не вышел. Опять же, наиболее вероятная причина в том, что входной канал не закрыт. Итак, где он открыт?

Он не будет открыт в процессе cat, потому что нет причин, по которым он не завершился бы.

Он не будет открыт в родительском процессе, потому что вы тщательно закрыли все дескрипторы.

Он не будет открыт в процессе cut, потому что вы закроете конец записи fd1.

Это оставляет сам процесс sort: у которого все еще открыты дескрипторы fd1!

Итак, sort зависает, потому что ждет завершения cut, а cut зависает, потому что ждет sort, хотя sort никогда ничего не запишет в fd1.

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

Во всяком случае, это моя теория.

person ams    schedule 30.11.2012