Эта строка - dup2(fds[PIPE_READ], 0);
- перезаписывает текущий дескриптор файла стандартного ввода дескриптором, ссылающимся на канал.Как только команда pipe завершается, любая попытка чтения из stdin завершится неудачей.
Эта строка - fgets(buf, BUF_LENGTH, stdin);
- не проверяет наличие ошибок.
Наконец - вы ждетевторой процесс в трубе, чтобы закончить, прежде чем вы начнете второй.Это то, что вызывает твой тупик;команда "grep" ожидает ввода, но вы еще не выполнили команду "ls".Вы ждете завершения команды grep, но она не может завершиться, потому что ожидает ввода.
В вашем последнем воплощении кода: когда вызывается функция execute (), она сканируетаргументы и находит трубу;затем он разветвляется и запускает первую команду ("ls"):
pid_t pid = fork();
if(pid == 0) {
dup2(fds[PIPE_WRITE], 1);
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
argArray[i] = 0;
execvp(argArray[0], &argArray[0]);
printf("%s: command not found.\n", argArray[0]);
exit(1);
Затем он повторяется, снова вызывая execute ():
} else {
dup2(fds[PIPE_READ], 0);
execute(&argArray[i+1], 0, 1); // <--- HERE
... это, конечно, forkи запустить "grep", прежде чем вернуться.Обратите внимание, что это происходит с / обоими / дескрипторами файловых каналов / open /.Поэтому сам процесс grep будет держать оба конца трубы открытыми.execute () выполняет ожидание (NULL) перед возвратом;это, однако, на самом деле будет ждать завершения «ls» (поскольку этот процесс завершается первым).Затем он возвращается и продолжает:
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
wait(pid); // <--- WRONG, compile with -Wall to see why
printf("herp\n");
}
Я указал на одну ошибку.Попробуйте скомпилировать с помощью "-Wall" или прочитайте документацию по функции wait ()!Если вы измените его на ожидание (NULL), оно будет правильным, однако в этом случае оно заблокируется.Причина в том, что команда "grep" не завершила и все еще читает ввод.Причина, по которой он все еще читает ввод, состоит в том, что сам процесс grep имеет открытый конец записи канала !!Таким образом, grep никогда не видит «конец» ввода, поступающего из канала.Простое решение - закрыть рекурсивный вызов fd канала перед рекурсивным вызовом (однако с вашим кодом остаются другие проблемы, в том числе, как я уже указывал, что вы уничтожаете свой дескриптор stdin).