c - 标准I/O流——fgets()缓冲类型

标签 c unix fgets io-buffering

《unix环境下的高级编程》一书在第15章讨论了管道,这表明我们在处理标准I/O函数时应该注意缓冲类型。

不同开放标准 I/O 流的缓冲类型为(本书第 5 章中讨论):

  • 标准错误无缓冲
  • 连接到终端设备的流是行缓冲
  • 所有其他流都是全缓冲

当父/子连接到管道时,它们用于通信的末端(根据接口(interface),应该是FILE *类型对象)应该是根据上面的规则列表完全缓冲(因为它是连接到管道的流)。但是该章中的示例代码的行为似乎不是完全缓冲

这里是示例代码:

myuclc.c:

1   #include "apue.h"
2   #include <ctype.h>

3   int
4   main(void)
5   {
6       int     c;

7       while ((c = getchar()) != EOF) {
8           if (isupper(c))
9               c = tolower(c);
10          if (putchar(c) == EOF)
11              err_sys("output error");
12          if (c == '\n')
13              fflush(stdout);
14      }
15      exit(0);
16  }

popen1.c:

1   #include "apue.h"
2   #include <sys/wait.h>

3   int
4   main(void)
5   {
6       char    line[MAXLINE];
7       FILE    *fpin;
8
9       if ((fpin = popen("myuclc", "r")) == NULL)  // "myuclc" is executable file compile-link by "myuclc.c"
10          err_sys("popen error");
11      for ( ; ; ) {
12          fputs("prompt> ", stdout);
13          fflush(stdout);
14
15          if (fgets(line, MAXLINE, fpin) == NULL) /* read from pipe */
16              break;
17          if (fputs(line, stdout) == EOF)
18              err_sys("fputs error to pipe");
19      }
20      if (pclose(fpin) == -1)
21          err_sys("pclose error");
22      putchar('\n');
23      exit(0);
24  }

所以我的问题是:根据缓冲规则,popen1.c第15行中的fgets()应该是完全缓冲,为什么它的行为类似于行缓冲无缓冲:

此外,我还尝试在 fgets() 之前使用 setvbuf() 将缓冲类型专门设置为 _IOFBF (全缓冲) fpin,还是不行。

prompt> abc
abc
prompt> ABC
abc
prompt> efg
efg
prompt> EFG
efg
prompt>

最佳答案

在 myuclc.c 中,您对每个换行符执行显式刷新:

12          if (c == '\n')
13              fflush(stdout);

这会导致流被手动行缓冲。每当您刷新管道时,另一端的进程将被解除阻塞,并将读取当时缓冲区中的所有内容。

“缓冲规则”讨论了这种刷新何时自动发生。无缓冲流在每个写入命令(fprintf、fputc 等)后自动刷新。每当将换行符写入流时,行缓冲流就会自动刷新。

当缓冲区填满、关闭流或编写器执行显式刷新时,所有流都会被刷新

关于c - 标准I/O流——fgets()缓冲类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39295791/

相关文章:

linux - 如何在 Curl 字符串中使用公历时间戳

bash - 如何在没有顶级文件夹的情况下压缩文件但保留子文件夹

unix - Deflate压缩 block 的结构

php - 使用 PHP 解析的大型 .txt 文件 (15.5mb)

c - 将 char* 设置为 NULL 段错误

c - 在 Char 数组中查找字符串值

无法弄清楚 C 中的中止(核心转储)

C:使用 fgets 读取用户输入时出现段错误

c - 为什么 fgets 正在读取输入,即使输入字符串中有 EOF?

C:访问分配内存中的字节