Использование системного вызова pipe () - PullRequest
5 голосов
/ 08 октября 2011

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

К сожалению, мне не особо повезло с использованием pipe (). Потратив несколько дней на просмотр различных онлайн-ресурсов, я решил собрать слишком упрощенную программу, которая дает тот же эффект, что и выполнение ls | sort, чтобы посмотреть, смогу ли я даже заставить канал работать для двух дочерних, дочерних процессов. Вот код:

#include <sys/wait.h>
#include <unistd.h>

void run(char *cmd) {
   char *args[2];
   args[0] = cmd;
   args[1] = NULL;

   execvp(cmd, args);
}

int main(void) {
    int filedes[2];
    pipe(filedes);

    pid_t pid_a, pid_b;

    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        run("ls");
    }

    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        run("sort");
    }

    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);

    return 0;
}

Канал создается в родительском объекте, и я знаю, что после вызова execvp () каждый дочерний процесс наследует файловые дескрипторы, которые pipe () создает в родительском объекте. Для процесса ls я использую dup2 () для перенаправления его стандартного out (1) на конец записи канала, а для процесса sort стандарт в (0) перенаправляется на чтение конец трубы.

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

Моя интуиция говорит мне, что это должно работать, но это не так!

Есть предложения?

Ответы [ 4 ]

6 голосов
/ 08 октября 2011

Вы должны закрыть трубы, которые вы не используете. по крайней мере sort будет читать с его стандартного ввода до тех пор, пока стандартный вывод не будет закрыт.

В этом случае его стандартный ввод никогда не закрывается, так как у вас все еще есть 2 открытых файловых дескриптора для него.

  • filedes [0] в дочернем элементе ls (вероятно, закрывается после завершения ls)
  • filedes [0] в родительской программе (это никогда не закрывается, так как вы ожидаете waitpid () для сортировки до конца, но никогда не закрывается, потому что родитель сохраняет свой стандартный stdin открытым)

Измените вашу программу на

if (!(pid_a = fork())) {
    dup2(filedes[1], 1);
    closepipes(filedes);
    run("ls");
}

if (!(pid_b = fork())) {
    dup2(filedes[0], 0);
    closepipes(filedes);
    run("sort");
}
closepipe(filedes);
waitpid(pid_a, NULL, 0);
waitpid(pid_b, NULL, 0);

где closepipes - это что-то вроде

void closepipes(int *fds)
{ 
 close(fds[0]);
 close(fds[1]);
}
4 голосов
/ 08 октября 2011

Перед вызовом waitpid в родительском процессе вы должны закрыть все файловые дескрипторы из конвейера, который вам не нужен.Это:

  • filedes[0] в pid_a
  • filedes[1] в pid_b
  • и filedes[0], и filedes[1] в родительском процессе

Вы также должны проверить, что pipe() и fork() не вернули -1, что означает, что произошла ошибка.

3 голосов
/ 08 октября 2011

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

1 голос
/ 06 сентября 2012

Этот код работает правильно ...

    #include <sys/wait.h>
    #include <unistd.h>
    using namespace std;

    void run(char *cmd) {
       char *args[2];
       args[0] = cmd;
       args[1] = NULL;

       execvp(cmd, args);
    }
    void closepipe(int *fds)
    { 
     close(fds[0]);
     close(fds[1]);
    }

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

        int filedes[2];
        pipe(filedes);
        char lss[]="ls";
        char sorts[]="sort";
        pid_t pid_a, pid_b;
     chdir(argv[1]);
    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        closepipe(filedes);
        run(lss);
    }

    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        closepipe(filedes);
        run(sorts);
    }
    closepipe(filedes);
    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);

        return 0;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...