2014-03-12 5 views
0

Я работаю над заданием, в котором мне нужно несколько процессов (родительский и детский) для общения. Родитель отправляет пути к файлам детям, и им необходимо запустить linux file (/ usr/bin/file), возвращая выходные данные отцу.Не получаю все линии от трубы

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

Я собираюсь отправить несколько путей к файлам для каждого дочернего элемента (пакет файлов), а затем читать file.

Проблема:

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

Код:

#define Read   0 
#define Write   1 
#define ParentRead  read_pipe[0] 
#define ParentWrite  write_pipe[1] 
#define ChildRead  write_pipe[0] 
#define ChildWrite  read_pipe[1] 
#define PIPE_BUF_LEN 4096 

using namespace std; 
int main() 
{ 
    /** Pipe for reading for subprocess */ 
    int read_pipe[2]; 
    /** Pipe for writing to subprocess */ 
    int write_pipe[2]; 
    char buffer[PIPE_BUF_LEN] = ""; 
    if (pipe(read_pipe) == 0 && pipe(write_pipe) == 0) 
    { 
     pid_t pid = fork(); 
     if (pid == -1) 
     { 
      fprintf(stderr, "Fork failure"); 
      exit(EXIT_FAILURE); 
     } 
     else if (pid == 0) //Child process 
     { 
      close(ParentRead); 
      close(ParentWrite); 
      dup2 (ChildRead, STDIN_FILENO); /*redirect ChildRead to stdin*/ 
      dup2 (ChildWrite, STDOUT_FILENO); /*redirect stdout to ChildWrite*/ 
      char* paramArgs[]={"/usr/bin/file","-n","-f-",NULL}; 
      execv("/usr/bin/file",paramArgs); 
      exit(EXIT_FAILURE); 
     } 
     else { //Parent process 
      close(ChildRead); 
      close(ChildWrite); 

      for (int i=0; i < 3 ;i++) 
      { 
       /*write to processes which are ready for writing: */ 
       fd_set rfds; 
       int retval; 
       FD_ZERO(&rfds); 
       FD_SET(ParentWrite, &rfds); 
       retval = select(10, NULL, &rfds, NULL, NULL); 
       if (retval == -1) 
       { 
        perror("select()"); 
       } 
       else if (retval) 
       { 
        write(ParentWrite, "file1\nfile2\n", 12); 
       } 
       /*read from processes which are ready for reading*/ 
       FD_ZERO(&rfds); 
       FD_SET(ParentRead, &rfds); 
       retval = select(10, &rfds, NULL, NULL, NULL); 
       if (retval == -1) 
       { 
        perror("select()"); 
       } 
       else if (retval) 
       { 
        read(ParentRead, buffer, PIPE_BUF_LEN); 
        cout << buffer; 
       } 
      } 
     } 
    } 
    exit(EXIT_SUCCESS); 
} 

В этом случае я пытаюсь запустить file на "file1 \ nfile2 \ п" (обратите внимание на -n -F- флаги, используемые) в цикле 3 итерации , ожидая получить шесть строк, но получить только три:

file1: ERROR: cannot open `file1' (No such file or directory)

file2: ERROR: cannot open `file2' (No such file or directory)

file1: ERROR: cannot open `file1' (No such file or directory)

Когда я не перенаправить вывод ребенка на трубе (позволяя ему писать в std_out), я получаю все шесть строк.

Любая помощь будет оценена по достоинству.

+0

Вы не можете получить столько байтов, сколько вы просите при чтении. Если вы распечатываете, сколько байтов читает родитель, вы увидите, что вы получаете короткие чтения. – Duck

+0

Да, но почему я получаю эти короткие чтения? Как я могу получить все строки, выведенные при вызове файла? – Paz

ответ

0

Планировщик. Вы находитесь в цикле, который просит ребенка (т. Е. Pgm file) искать два файла три раза. Вы только один читаете за цикл в родительском.

  • Если ребенок запланирован и не прерывается, он выполняет поиск первого файла, записывает трубу, выполняет второй поиск, записывает в трубу. Родитель получает запланированное задание, и вы читаете полный вывод ребенка в одном чтении. Ты золотой (но повезло).
  • Ребенок запланирован, первый поиск и запись на трубе и прерываются. Родитель читает один вывод. Ребенок перепланируется и выполняет второй поиск и записывает трубу. Родитель читает один вывод. Поскольку вы читаете только 3 раза, вы получаете только 3 из 6 выходов.
  • Вариации на вышесказанное. Возможно, вы прочтете 1 выход, затем 3, затем 1. Вы просто не знаете.

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^