Chinaunix首页 | 论坛 | 博客
  • 博客访问: 364871
  • 博文数量: 83
  • 博客积分: 5322
  • 博客等级: 中校
  • 技术积分: 1057
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-11 11:27
个人简介

爱生活,爱阅读

文章分类

全部博文(83)

文章存档

2015年(1)

2013年(1)

2012年(80)

2011年(1)

分类: LINUX

2012-04-09 21:44:00

关于Linux下的I/O缓存有三种模式:块缓冲,行缓冲与无缓冲。

函数原型:

#include

void setbuf(FILE *stream, char *buf); 
   void setbuffer(FILE *stream, char *buf, size_t size); 
   void setlinebuf(FILE *stream); 
   int setvbuf(FILE *stream, char *buf, int mode , size_t size);  

函数描述:

有三种类型的缓冲策略,它们是无缓冲,块缓冲和行缓冲。当输出流无缓冲时,信息在写的同时出现于目标文件或终端上;当是块缓冲时,字符被暂存,然后一起写入;当是行缓冲时,字符被暂存,直到要输出一个新行符,或者从任何与终端设备连接的流中 (典型的是 stdin) 读取输入时才输出。函数 fflush(3) 可以用来强制提前输出。(参见 fclose(3)) 通常所有文件都是块缓冲的。当文件 I/O 操作在文件上发生时,将调用 malloc(3) ,获得一个缓冲。如果流指向一个终端 (通常 stdout 都是这样),那么它是行缓冲的。标准错误流 stderr 默认总是无缓冲的。

函数 setvbuf 可以用在任何打开的流上,改变它的缓冲。参数 mode 必须是下列三个宏之一:

   _IONBF:无缓冲    _IOLBF:行缓冲    _IOFBF:完全缓冲

除非是无缓冲的文件,否则参数 buf 应当指向一个长度至少为 size 字节的缓冲;这个缓冲将取代当前的缓冲。如果参数 buf  NULL ,只有这个模式会受到影响;下次 read 或 write 操作还将分配一个新的缓冲。函数 setvbuf 只能在打开一个流,还未对它进行任何其他操作之前使用。

其他三个函数调用是函数 setvbuf 的别名,函数 setbuf 与使用下列语句完全等价:

setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);

函数 setbuffer 与此相同,但是缓冲的长度由用户决定,而不是由默认值 BUFSIZ 决定。函数 setlinebuf 与使用下列语句完全等价:

setvbuf(stream, (char *)NULL, _IOLBF, 0);    函数返回值:

函数 setvbuf 成功执行时返回 0。它失败时可能返回任何值。其他函数没有返回值。  

另:

标准I/O 库函数通常带有缓冲机制,如 printf() 函数。

1、当标准输入stdin/输出stdout连接到终端,则其为行缓冲,即以换行符为标记,将缓冲区写入文件(终端),同时清空缓冲区。但行缓冲是有限的,如果一行输入超出了行缓冲区的范围,则直接调用write写入终端而不会继续等待换行符。

2、当标准输入stdin/输出stdout重新定向到一个普通文件,则其为块缓冲,即虽然将缓冲区中的内容输出至文件,但缓冲区仍然保留其内容,未被清空。

3、标准错误输出stderr为无缓冲。

举例:

点击(此处)折叠或打开

  1. #include
  2. #include
  3. #include
  4. #include
  5. int glob = 26;
  6. char buf[] = "A test of calling write a buffer to the stdout\r\n";
  7. int main(int argc,char argv[])
  8. {
  9. int var;
  10. pid_t pid;
  11. var = 18;
  12. if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf) - 1)
  13. {
  14. perror ("write failed");
  15. exit (-1);
  16. }
  17. printf ("___BEFORE FORK\n");
  18. if ((pid = fork()) < 0)
  19. {
  20. perror ("fork failed");
  21. exit (-1);
  22. }
  23. else if (pid == 0)
  24. {
  25. glob++;
  26. var++;
  27. }
  28. else
  29. {
  30. if(wait(NULL)<0)
  31. {
  32. perror("wait failed");
  33. exit(-1);
  34. }
  35. }
  36. printf ("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
  37. exit(0);
  38. }

执行1:直接在终端执行

点击(此处)折叠或打开

  1. [admin@localhost lp]$ make -f testbuff.mk
  2. gcc -o testbuff testbuff.c
  3. [admin@localhost lp]$ ./testbuff
  4. A test of calling write a buffer to the stdout
  5. ___BEFORE FORK
  6. pid = 3789, glob = 27, var = 19
  7. pid = 3788, glob = 26, var = 18
  8. [admin@localhost lp]$

执行2:重定向到文件

点击(此处)折叠或打开

  1. [admin@localhost lp]$
  2. [admin@localhost lp]$ ./testbuff >0
  3. [admin@localhost lp]$ cat 0
  4. A test of calling write a buffer to the stdout
  5. ___BEFORE FORK
  6. pid = 3809, glob = 27, var = 19
  7. ___BEFORE FORK
  8. pid = 3808, glob = 26, var = 18
  9. [admin@localhost lp]$


 

阅读(1209) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~