The book "advanced programming in unix environment" discussed pipe in chapter 15, it shows that we should pay attention to the buffering type when deal with standard I/O functions.
The buffering types for different opened standard I/O streams are (discussed in chapter 5 of the book):
- standard error is
unbuffered
- streams connected to terminal devices is
line-buffered
- all other streams are
fully-buffered
When parent/child connect to a pipe
, the end (which should be a FILE *
type object, according to the interface) that they used to communicate should be fully-buffered
according to the rule list above (since it's a stream connected to pipe
). But the behavior of sample code from that chapter seems to be something NOT fully-buffered
.
Here is the sample code:
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 }
So my question is : fgets()
in line 15 of popen1.c
should be fully-buffered
according to the buffering rules, why does it act like line-buffered
or unbuffered
:
Furthermore, I also tried to setvbuf()
before fgets()
to specifically set buffering type to _IOFBF
(fully-buffered) of fpin
, still not work.
prompt> abc
abc
prompt> ABC
abc
prompt> efg
efg
prompt> EFG
efg
prompt>