两层buffer的存在
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 while(1){
28 char c[BUFSIZ];
29 retval = read(0, c, 1);
30 printf("%c\n", *c);
31 }
32 return 0;
33 }
上面的代码, 用户输入一次, read函数被调用N次(数据的长度)。也就是说用户输入的数据已经被缓存了。
再如下:
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 int i;
28 int c;
29 printf("%d\n", BUFSIZ);
30 for(i = 0; i < BUFSIZ / 2; i++){
31 c = fgetc(stdin);
32 }
33 return 0;
34 }
上面的代码fgetc被调用N次(数据的长度), 但是read的调用情况如下:
1. 当stdin不是terminate device时, 被调用一次, read的count参数为4096
2. 当stdin是terminate device时, 被调用两次, read的count参数为1024
* 至少怎么得到这种数据, 答案是使用strace凶器。
libc会根据stdin是什么使用setvbuf对FILE对象设置buffer.
从上面两个例子可以知道:
1. 使用standard I/O从terminate device读数据时, 其实经过了两个buffer机制。
2. standard I/O读不同file descriptor时的buffer大小会变化。 加上从APUE中知道的,情况会是这样
* 当stdin, stdout是terminate device时, standard I/O会使用行缓存, buffer大小为1024.
* 当stdin, stdout不是terminate device时, standard I/O会使用full buffer, buffer大小为4096.
好, 知道这两种buffer机制与buffer大小了, 移步看这一篇文章会有很好的收获:
* http://www.pixelbeat.org/programming/stdio_buffering/
这文章从一个例子开始, 如下:
# tail -f access.log | cut -d' '|uniq
为什么上面的命令没有输出? 呵呵, 其中就是IO缓存的机制.
预读数据, 减少read, write
使用standard I/O都是会预读一定数量的数据, 用于减少调用read, write的次数.
使用standard I/O的好处就是程序员无需操心这个预读数据的大小, 只需要知道它是预读的即可.
如果不知道会预读的话, 上面的URL的例子就无法明白.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.