2016-11-05 3 views
1

У меня есть домашняя работа, которая просит меня создать оболочку, которая выполняет несколько команд, разделенных конвейерами. Вот мой фрагмент кода для порождения Чайлдс и выполнения команд:Выполнение нескольких конвейеров и выполнение команд в C

for (int i = 0; i < commands; i++) { 

     place = commandStarts[i]; 

     if((pid = fork()) < 0) exit(1); 
     else if (pid == 0) { 
      if(i < pipe_counter && dup2(fds[j + 1], 1) < 0) exit(1);// If this is not the last remaining command 

      if(j != 0 && dup2(fds[j-2], 0) < 0) exit(1);  // If this is not the first command 

      for(int c = 0; c < 2*pipe_counter; c++) close(fds[c]); 

      if(execvp(argv[place], argv+place)) exit(0);  // Execute and if it returns anything, exit! 
     } 
     j+=2; 
    } 

    for(int i = 0; i < 2 * pipe_counter; i++) close(fds[i]); 

    while ((wait(&status)) != pid);      // The only program that gets to this point is the 
             //  parent process, which should wait for completion 

Несмотря на то, что, кажется, работает очень хорошо в простых примерах, в некоторых более сложная система классификации дает мне эту ПОДСКАЗКА: Вы должны дождитесь завершения всех процессов в цепочке трубопроводов перед отображением подсказки, а не только для последней!

Можете ли вы сказать, где моя ошибка?

+0

В каком коде вы ожидаете завершения каждого процесса? – wallyk

+0

Как вы можете видеть в конце фрагмента, я жду завершения всех процессов за один цикл! –

+0

Вы? Как это работает? ... Точно. Я не думаю, что это работает, как вы думаете. – wallyk

ответ

1

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

Вот правильный фрагмент кода, который ждет каждый ребенка прекратить:

for (int i = 0; i < commands; i++) { 

     place = commandStarts[i]; 

     if((pid = fork()) < 0) exit(1); 
     else if (pid == 0) { 
      if(i < pipe_counter && dup2(fds[j + 1], 1) < 0) exit(1);// If this is not the last remaining command 

      if(j != 0 && dup2(fds[j-2], 0) < 0) exit(1);   // If this is not the first command 

      for(int c = 0; c < 2*pipe_counter; c++) close(fds[c]); 

      if(execvp(argv[place], argv+place)) exit(1);   // Execute and if it returns anything, exit! 
     } 
     j+=2; 
    } 

    for(int i = 0; i < 2 * pipe_counter; i++) close(fds[i]); 

    for(int i = 0; i < commands; i++) wait(&status);   // The only program that gets to this point is the 
                   //  parent process, which should wait for completion. 

Также большое спасибо wallyk за помощь мне кажется, это через!

+0

Хотя это намного ближе к надежной реализации, у него есть тот недостаток, что он будет сокрушен любыми внуками, которые получаются 'wait()'. Вы можете отслеживать дочерние pids как сгенерированные и ждать цикла ожидания для этих конкретных идентификаторов. – wallyk

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