自从我上一次用C编程以来已经有一段时间了,我在使管道正常工作方面遇到了麻烦。 (为清楚起见,我在Windows 7上使用Cygwin。)特别地,我需要帮助了解以下示例的行为:
/* test.c */
#include <stdio.h>
#include <unistd.h>
int main() {
char c;
//scanf("%c", &c); // this is problematic
int p[2];
pipe(p);
int out = dup(STDOUT_FILENO);
// from now on, implicitly read from and write on pipe
dup2(p[0], STDIN_FILENO);
dup2(p[1], STDOUT_FILENO);
printf("hello");
fflush(stdout);
// restore stdout
dup2(out, STDOUT_FILENO);
// should read from pipe and write on stdout
putchar(getchar());
putchar(getchar());
putchar(getchar());
}
如果我调用:
echo abcde | ./test.exe
我得到以下输出:
hel
但是,如果我取消对scanf
通话的评论,则会得到:
bcd
我无法解释。实际上,这是具有fork/exec
结构的更复杂程序的非常简化的版本,开始表现很差。尽管没有周期,但它以某种方式开始以无休止的循环产生无限的孩子。因此,在规则允许的情况下,我可能需要使用更具体的使用案例来扩展问题。非常感谢。
答案 0 :(得分:4)
诸如scanf
之类的流I / O函数通常执行缓冲以提高性能。因此,如果您在标准输入上调用scanf
,则它可能会读取比满足请求所需的字符更多的字符,并且多余的字符将等待缓冲,以备下一次读取。
交换基础文件描述符不会影响以前缓冲的数据。当您随后再次读取该文件时,您将第一次缓冲数据,直到数据用尽为止,然后才从新的基础文件中获取新数据。
如果愿意,可以在执行任何I / O操作之前通过setvbuf()
函数关闭流的缓冲:
int result = setvbuf(stdin, NULL, _IONBF, 0);
if (result != 0) {
// handle error ...
}
这实际上是更复杂程序的非常简化的版本 带有fork / exec结构,开始表现很差。尽管没有 有了周期,它就以某种方式开始在一个 无休止的循环。
我不知道这种行为与您在这里提出的要求有什么联系。
因此,在规则允许的情况下,我可能需要扩展 一个更具体的使用案例的问题。
那将是一个单独的问题。