Вы не закрываете достаточно файловых дескрипторов в дочернем элементе.
Правило большого пальца : Если вы dup2()
один конец канала для стандартного вводаили при стандартном выводе закройте оба исходных дескриптора файла, возвращенных pipe()
, как можно скорее.В частности, вы должны закрыть их перед использованием любого из семейства функций exec*()
.
Правило также применяется, если вы дублируете дескрипторы с dup()
или fcntl()
с F_DUPFD
В этом случае ребенок должен закрыть fds[1]
после его дублирования.Поскольку он все еще открыт, rev
никогда не получит EOF, потому что существует процесс (rev
дочерний процесс), который теоретически может записывать данные на вход.
Вместо этого следует использовать fclose(stream)
close(fds[1])
, потому что вывод буферизован и fclose()
знает, что нужно очистить буферы, но close()
не имеет понятия.Однако, используя fflush(stream)
перед ошибочным close()
, вы избегаете проблем.
Это приводит к:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if (pid == (pid_t)0)
{
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[1]);
execlp("rev", "rev", 0);
}
else
{
FILE *stream;
close(fds[0]);
stream = fdopen(fds[1], "w");
fprintf(stream, ",ereh ot ereht morF\n");
fprintf(stream, ",ereht ot ereh dna\n");
fprintf(stream, ".erehwyreve era sgniht ynnuf\n");
fprintf(stream, "ssueS .rD - \n");
fclose(stream);
waitpid(pid, NULL, 0);
}
return 0;
}
, который производит вывод:
From there to here,
and here to there,
funny things are everywhere.
- Dr. Seuss