Трубы, подключенные к выводу stdio print после запроса нового терминала - PullRequest
0 голосов
/ 19 ноября 2018

У меня проблемы с пониманием того, как выполнять основные трубопроводы в C. Я посмотрел на пару других вопросов по этой теме, или они были для слегка разных вопросов, или я так далеко от цели в этой теме, я не мог понять, почему ответы хороши для моей проблемы.

Эта программа, представленная ниже, является простым тестом, в котором я пытаюсь получить поведение, эквивалентное вводу «ls | grep a» в мою оболочку. (У меня есть домашнее задание, где я должен создать оболочку, которая может обрабатывать трубопроводы, но это мой первый шаг к пониманию труб, чтобы даже попытаться выполнить домашнюю работу). Я получаю правильный вывод, но подсказка терминала в конечном итоге появляется перед выводом, создавая впечатление, что он не завершается должным образом. Так как это связано с домашним заданием по оболочке, я беспокоюсь, что это повлияет на оценку (и все равно кажется неправильным, чтобы это выглядело так). Любой совет?

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

int main()
{
    int fdpipe[2];


    pipe(fdpipe);
    int f1 = fork();
    if(f1 == 0)
    {
        close(fdpipe[1]);
        dup2(fdpipe[0],0);
        close(fdpipe[0]);
        execlp("/bin/grep","grep","a",NULL);
    }
    else
    {
        close(fdpipe[0]);
        dup2(fdpipe[1],1);
        close(fdpipe[1]);
        execlp("/bin/ls","ls",NULL);
        wait(NULL);
    }
    return 0;
}

Вот пример вывода моего терминала.

1067: ls
a.out  test.c  test.cc
NathanE: ~/Desktop/playground
1068: ./a.out 
NathanE: ~/Desktop/playground
1069: a.out
(The beginning of this line is where my cursor is)

То, что я ожидаю, будет:

1067: ls
a.out  test.c  test.cc
NathanE: ~/Desktop/playground
1068: ./a.out 
a.out
NathanE: ~/Desktop/playground
1069: (my cursor would go here)

1 Ответ

0 голосов
/ 19 ноября 2018

Дочерний процесс запускается grep, в то время как родитель заменяет себя на ls. wait(NULL) ничего не делает, потому что успешное exec*() никогда не вернется.

Поскольку элемент управления возвращается в оболочку сразу после завершения ls, оболочка может отображать следующее приглашение до завершения grep.

Есть два подхода, которые можно использовать, чтобы избежать этого:

  1. fork() оба дочерних процесса и wait() для них

  2. Заменить сам процесс на последний процесс в цепочке труб

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

...