не могу прочитать из потока, пока ребенок не выйдет? - PullRequest
5 голосов
/ 26 апреля 2010

ОК. У меня есть программа, которая создает две трубы -> вилки -> дочерний stdin и stdout перенаправляются на один конец каждой трубы -> родительский элемент подключается к другим концам каналов и пытается прочитать связанный поток с выводом дочернего элемента и распечатайте его на экране (и я также в конечном итоге заставлю его записать на вход дочернего элемента).

Проблема в том, что когда родитель пытается fgets выходной поток дочернего элемента, он просто останавливается и ждет, пока дочерний элемент не умирает, чтобы fgets, а затем печатает выходные данные. Если ребенок не выходит, он просто ждет вечно. Что здесь происходит? Я думал, что, возможно, fgets будет блокировать, пока SOMETHING не окажется в потоке, но не заблокировать полностью, пока ребенок не откажется от файловых дескрипторов.

Вот код: </p> <pre><code>#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char *argv[]) { FILE* fpin; FILE* fpout; int input_fd[2]; int output_fd[2]; pid_t pid; int status; char input[100]; char output[100]; char *args[] = {"/somepath/someprogram", NULL}; fgets(input, 100, stdin); // the user inputs the program name to exec pipe(input_fd); pipe(output_fd); pid = fork(); if (pid == 0) { close(input_fd[1]); close(output_fd[0]); dup2(input_fd[0], 0); dup2(output_fd[1], 1); input[strlen(input)-1] = '\0'; execvp(input, args); } else { close(input_fd[0]); close(output_fd[1]); fpin = fdopen(input_fd[1], "w"); fpout = fdopen(output_fd[0], "r"); while(!feof(fpout)) { fgets(output, 100, fpout); printf("output: %s\n", output); } } return 0; }

1 Ответ

5 голосов
/ 26 апреля 2010

Дочерний объект, вероятно, должен <a href="http://en.cppreference.com/w/c/io/fflush" rel="nofollow noreferrer">fflush()</a> выводить и / или правильно завершать строки. В противном случае буферизация ввода / вывода может довольно долго зависать от данных.

Вы можете попытаться установить флаг O_NONBLOCK (используя <a href="http://linux.die.net/man/2/fcntl" rel="nofollow noreferrer">fcntl()</a>) в дескрипторе выходного файла дочернего элемента перед передачей управления, но для этого потребуется соответственно изменить родительский код. Как отмечалось в комментариях, это не поможет вам преодолеть буферизацию, выполняемую на уровне стандартной библиотеки C, если ребенок использует FILE -основной ввод-вывод.

...