Используя Pipe в C, да | голова идет в бесконечном цикле

После этого SO вопрос и ответ

Соединение n команд с каналами в оболочке?

Я попытался выполнить yes | head, но он работает в бесконечном цикле или никогда не отвечает. В чем проблема.

Я внес некоторые изменения, и вот рабочий код

#include <unistd.h>

struct command
{
    const char **string;
};

Вспомогательная функция

pid_t start(command* command, pid_t pid, int* status, int in, int out) {
    (void) pid;
    pid_t cpid;
    int childInt;

    cpid = fork();
    if (cpid == 0) {

        if (in != 0)
        {
            dup2(in, 0);
            close(in);
        }


        if (out != 1)
        {
            dup2(out, 1);
            close(out);
        }

            execvp(c->string[0], c->string);
            _exit(1);
        }

        waitpid(cpid, &childInt, 0);
    }


    *status = childInt;
    return c->pid;
}

и в моей основной функции

for(int i = 0; i < n; i++)
    //New command every loop
    int p = pipe(fd);
    if (p == 0)
    {
        start_command(c, 0, &status, in, fd[1]);
        close(fd[1]);
        in = fd[0];
    }
    continue;
}
dup2(in, 0);

person Basit Anwer    schedule 23.03.2019    source источник
comment
Какой у Вас вопрос? Вы можете еще раз взглянуть на свой код и собрать минимально воспроизводимый пример, который компилируется.   -  person Retired Ninja    schedule 23.03.2019
comment
ваша start_command ожидает завершения команды... так что спросите себя, выполняете ли вы yes и ждете её завершения (чего никогда не происходит, так как вы держите другой конец труба открыта)... и даже не доходит до выполнения head   -  person Antti Haapala    schedule 23.03.2019
comment
Код работает нормально. Ошибка заключалась в чтении файла, из которого я читал команды для выполнения. Застал меня врасплох.   -  person Basit Anwer    schedule 25.03.2019


Ответы (1)


Если вы хотите выполнить yes | head, вам нужно создать два процесса, yes и head, и вам нужно соединить их с помощью канала. У вас нет кода для этого, вы просто выполняете yes и передаете его | head. Это заставляет yes выводить "| head" снова и снова.

Вы не можете просто передать yes и | head в execvp. Вы можете execvp оболочку и передать ее yes | head, так как оболочки имеют необходимый код для создания конвейеров, порождения нескольких процессов и их надлежащего подключения.

person David Schwartz    schedule 23.03.2019
comment
Я пытался внедрить конвейер оболочки в свой код, поэтому его совместное выполнение убивает цель. Так вы говорите, что я не должен использовать execvp? - person Basit Anwer; 24.03.2019
comment
Я думаю, что понял. Я выполняю сначала перед запуском другого исполняемого канала. Сначала нужно запустить ребенка, а затем родителя. - person Basit Anwer; 24.03.2019
comment
@BasitAnwer Сначала вам нужно создать канал! - person David Schwartz; 24.03.2019