Unix系统的三种缓冲区行缓冲、全缓冲、无缓冲(以及如何调整缓冲区的类型)
来源:互联网 发布:amazon数据分析工具 编辑:程序博客网 时间:2024/06/05 08:26
from unix系统编程 p91 练习4-22
下面的程序会产生什么样的输出呢?
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("This is my output.") ;
fork() ;
return 0 ;
}
输出如下所示:
This is my output.This is my output.
(似乎很不正常!该程序中,一个printf语句输出之后,用fork函数创建子进程,然后父子进程一起返回。
怎么会输出两个printf语句呢??)
其实,
由于缓冲的原因,printf的输出可能会写入stdout所对应的缓冲区中,而不会被写入实际的输出设备。由于这个缓冲区是用户空间的一部分,所有它会被fork复制。父进程和子进程每次终止时,从main的返回都会将缓冲区作为清理的一部分清空。
而下面的程序会产生什么样的输出呢?
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("This is my output.\n") ; /*注意,原字符串后多了一个 \n */
fork() ;
return 0 ;
}
输出如下显示:
This is my output.
标准输出的缓冲通常是行缓冲,这意味着当新行包含新行的时候,缓冲区会被清空,所以会在fork之前被清空,只输出一行输入。
磁盘文件是完全缓冲的(fully buffered),程序调用fprintf时,实际上没有把消息写入磁盘,而是将这些字节写人如FILE结构的一个缓冲区中,可用fflush调用强制写出缓冲的任何内容。
与终端有关的文件是行缓冲(line buffered)的。
标准错误(strerror)默认情况下是不缓冲的。
附件1:
在Unix系统中,缓冲方式存在三种,分别是:
1,全缓冲
2,行缓冲
3,无缓冲
在学习APUE这本书时,程序8-1中,就很好的体现了全缓冲和行缓冲的区别,代码如下:
- #include<stdio.h>
- #include<unistd.h>
- int glob=6;
- char buf[]="a write ro stdout/n";
- int main()
- {
- int var;
- pid_t pid;
- printf("a write to stdout/n");
- fflush(NULL);
- if((pid=fork())<0)
- {
- printf("fork error");
- }
- else
- {
- if(pid==0)
- {
- glob++;
- var++;
- }
- else
- {
- sleep(2);
- }
- }
- printf("pid=%d,glob=%d,var=%d/n",getpid(),glob,var);
- exit(0);
- }
编译成功后,我这里生成的二进制文件默认为a.out
运行:./a.out
可以看到结果如下:
- a write to stdout
- pid=6587,glob=7,var=134514042
- pid=6586,glob=6,var=134514041
运行./a.out > temp.out
结果如下:
- a write to stdout
- pid=6591,glob=7,var=134514042
- a write to stdout
- pid=6590,glob=6,var=134514041
分析原因:
在./a.out输出中,标注输出是STDOUT_FILENO,是交互式的终端,所以系统采用的缓冲方式行缓冲,所以在printf函数中,输出后,立即刷新缓冲区,而在./a.out > temp.out命令中,输出流定向到了temp.out文件中,所以采用的输出方式为全缓冲方式,所以会两次输出
a write to stdout
可以将程序中fflush(NULL)加入,则只会输出一次
a write to stdout
因为flush即时刷新了缓冲区。
附件2:
使用缓冲区的目的:尽量减少使用read/write的调用
分类:
1. Fully buffered means that I/O takes place only when the buffer is fully, the process explicitly calls fflush, or the process terminates by calling exit. A common size for the standard I/O buffer is 8192 bytes;
2. Line buffered means that I/O takes place when a newline is encountered, when the process calls fflush, or when the process terminates by calling exit.
3. Unbuffered means that I/O take place each time a standard I/O output function is called.
Most unix implementations of the standard I/O libarary use the following rules.
1. Standard error is always unbuffered. 能够快速显示错误
2. Standard input and standard output are fully buffered, unless they refer to a terminal device, in which case, they are line buffered.
3. All other streams are fully buffered unless they refer to a terminal device,
in which case, they are line buffered.
使用setbuf()和setvbuf()可以更改缓冲的类型:
setbuf(FILE *fp, char *buf) buf用malloc()开辟,当buf为NULL时,缓冲区为不带缓冲
setvbuf(FILE *fp,char *buf, int buf_mode, int size)
buf_mde有三种:_IOFBF 0 全缓冲, _IOLBF 1 行缓冲, _IONBF 2 不带缓冲
在任何时刻,可以使用fflush强制刷新一个数据流,此函数使该流所有未写的数据都被传递至内核。
由于fflush(stdin)的移植性不好,gcc不支持,故可以用以下代码清空stdin缓冲区:
while ((c = getchar()) != '\n' && c != EOF);
- Unix系统的三种缓冲区行缓冲、全缓冲、无缓冲(以及如何调整缓冲区的类型)
- 基于流的I/O提供以下3种缓冲:全缓冲、行缓冲、无缓冲
- 缓冲、缓冲区、缓存三者的区别
- C的全缓冲、行缓冲和无缓冲
- C标准I/O缓冲区:全缓冲和行缓冲
- C标准I/O缓冲区:全缓冲和行缓冲
- 标准的I/O缓冲:全缓冲,行缓冲,无缓冲
- 验证stderr stdout stdin 缓冲类型和缓冲区大小 以及在重定向后缓冲类型的改变
- 【转】基于流的I/O提供以下3种缓冲:全缓冲、行缓冲、无缓冲
- 行缓冲、全缓冲、无缓冲
- python 5-3 如何设置文件的全缓冲(硬盘 缓冲大小满了,就落盘),行缓冲(tty),无缓冲(串口)
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲 .
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲
- 全缓冲和行缓冲的区别
- 全缓冲和行缓冲的区别
- 标准I/O缓冲 与 用户程序的行缓冲区
- [转载] 在Tiled Map中使用碰撞检测
- hdu4336 状态压缩dp+概率论
- 题目1070:今年的第几天?
- 算法导论------------计数排序and基数排序
- For my dream
- Unix系统的三种缓冲区行缓冲、全缓冲、无缓冲(以及如何调整缓冲区的类型)
- AD9制作负片时孔颜色设置解决方法
- linux touch 命令
- 单点/多点接地方式分析
- 刚好经过合法的活动符合规范的官方订购
- Admob(6.12.x)符号未定义错误的解决方法(IOS)
- 题目1069:查找学生信息
- Linux磁盘存储入门
- 发帖骨头个人结果让他几乎覆盖