Выполнение команды UNIX выводится после выхода из программы - PullRequest
1 голос
/ 08 октября 2019

По какой-то неизвестной причине, когда я выполняю конвейерные команды в своей оболочке, они выводятся только после того, как я выйду из программы, кто-нибудь понимает, почему?

Код:

int execCmdsPiped(char **cmds, char **pipedCmds){

  // 0 is read end, 1 is write end 
  int pipefd[2]; 

  pid_t pid1, pid2; 

  if (pipe(pipefd) == -1) {
    fprintf(stderr,"Pipe failed");
    return 1;
  } 
  pid1 = fork(); 
  if (pid1 < 0) { 
    fprintf(stderr, "Fork Failure");
  } 

  if (pid1 == 0) { 
  // Child 1 executing.. 
  // It only needs to write at the write end 
    close(pipefd[0]); 
    dup2(pipefd[1], STDOUT_FILENO); 
    close(pipefd[1]); 

    if (execvp(pipedCmds[0], pipedCmds) < 0) { 
      printf("\nCouldn't execute command 1: %s\n", *pipedCmds); 
      exit(0); 
    }
  } else { 
    // Parent executing 
    pid2 = fork(); 

    if (pid2 < 0) { 
      fprintf(stderr, "Fork Failure");
      exit(0);
    }

    // Child 2 executing.. 
    // It only needs to read at the read end 
    if (pid2 == 0) { 
      close(pipefd[1]); 
      dup2(pipefd[0], STDIN_FILENO); 
      close(pipefd[0]); 
      if (execvp(cmds[0], cmds) < 0) { 
        //printf("\nCouldn't execute command 2...");
        printf("\nCouldn't execute command 2: %s\n", *cmds);
        exit(0);
      }
    } else {
      // parent executing, waiting for two children
      wait(NULL);
    } 
  }
}

Вывод:

Output of program when I enter

В этом примере вывода я использовал «ls | sort -r» в качестве примера, еще одно важное замечаниечто моя программа предназначена для обработки только одного канала, я не поддерживаю многопоточные команды. Но, учитывая все это, где я иду не так, и что я должен сделать, чтобы исправить это так, чтобы он выводился внутри оболочки, а не за ее пределами. Заранее большое спасибо за любые советы и помощь.

1 Ответ

1 голос
/ 09 октября 2019

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

Попробуйте закрыть оба pipefd[0] и pipefd[1] перед ожиданием завершения процесса.

Также обратите внимание, что wait(NULL); немедленно вернется после завершения одного процесса, вам понадобится второйчтобы не генерировать зомби, если ваш процесс все еще выполняется после этого.

...