将标准输出重定向到管道并从单个进程中读取
Redirecting stdout to pipe and reading from it from a single process
我正在将一个 Linux 程序移植到一个 没有 fork() 的系统,因此一切都在一个进程中运行。该程序创建管道,将 stdout 重定向到管道的输入,分叉,子级调用 printf,父级从管道读取数据。我删除了 fork,并尝试在 Linux 上测试它 - 程序挂在 read()
上等待管道上的数据。这是一个小型复制器:
#include <stdio.h>
#include <unistd.h>
const char in[7] = "qwerty";
int main ()
{
int fds[2], stdout_sav;
char str[8] = {0};
pipe(fds);
if ((stdout_sav = dup(1)) < 0) return 1; // save stdout
if (dup2(fds[1], 1) < 0) return 2; // stdout -> pipe
close(fds[1]);
if (printf(in) <= 0) return 3;
//fsync(1); // behavior does not change if I add a fsync here
read(fds[0], str, sizeof(in)); // HERE: read waits for data
close(fds[0]);
if (dup2(stdout_sav, 1) < 0) return 4; // restore stdout
close(stdout_sav);
printf("Received %s\n", str);
return 0;
}
因为它在 Linux 上不起作用,我想代码中的逻辑有误,但我没有发现任何问题。
我有一个想法,如果没有读者,单个进程将不会写入管道,但是,这不是真的,因为以下代码可以正常工作:
pipe(fds);
write(fds[1], in, sizeof(in));
close(fds[1]);
read(fds[0], str, sizeof(in));
close(fds[0]);
printf("Received %s\n", str);
您似乎忘记了当连接到管道时 stdout
是 完全 缓冲的。
您需要显式刷新 stdout
才能将数据实际写入管道。由于数据未刷新,管道中没有任何内容可读,read
调用块。
所以在 printf
调用之后你需要 fflush(stdout)
.
我正在将一个 Linux 程序移植到一个 没有 fork() 的系统,因此一切都在一个进程中运行。该程序创建管道,将 stdout 重定向到管道的输入,分叉,子级调用 printf,父级从管道读取数据。我删除了 fork,并尝试在 Linux 上测试它 - 程序挂在 read()
上等待管道上的数据。这是一个小型复制器:
#include <stdio.h>
#include <unistd.h>
const char in[7] = "qwerty";
int main ()
{
int fds[2], stdout_sav;
char str[8] = {0};
pipe(fds);
if ((stdout_sav = dup(1)) < 0) return 1; // save stdout
if (dup2(fds[1], 1) < 0) return 2; // stdout -> pipe
close(fds[1]);
if (printf(in) <= 0) return 3;
//fsync(1); // behavior does not change if I add a fsync here
read(fds[0], str, sizeof(in)); // HERE: read waits for data
close(fds[0]);
if (dup2(stdout_sav, 1) < 0) return 4; // restore stdout
close(stdout_sav);
printf("Received %s\n", str);
return 0;
}
因为它在 Linux 上不起作用,我想代码中的逻辑有误,但我没有发现任何问题。
我有一个想法,如果没有读者,单个进程将不会写入管道,但是,这不是真的,因为以下代码可以正常工作:
pipe(fds);
write(fds[1], in, sizeof(in));
close(fds[1]);
read(fds[0], str, sizeof(in));
close(fds[0]);
printf("Received %s\n", str);
您似乎忘记了当连接到管道时 stdout
是 完全 缓冲的。
您需要显式刷新 stdout
才能将数据实际写入管道。由于数据未刷新,管道中没有任何内容可读,read
调用块。
所以在 printf
调用之后你需要 fflush(stdout)
.