欢迎关注我的主页
注: 以下实验环境为Ubuntu 18.04LTS(只有64bit),gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
缓冲区例子
我们先来说说什么是C语言中的缓冲,直接来看一个例子体会一下就知道了。我们以printf
函数和stderr
为例,先说明stdout
(对应printf
)是遇到换行符或缓冲区满之后或程序结束后才输出缓冲,stderr
一般是无缓冲的:
/*
** 在我的实验环境中,缓冲区大小默认为1024
*/
#include <stdio.h>
int main()
{
while(1) {
printf(".");
fprintf(stderr, "1");
}
return 0;
}
(你可以数数,有1024个1,然后1024个’.’,…)
或者你可以通过用./a.out > t 2>&1
重定向标准输出和错误到文件t中,这样就可以很容易看到运行结果(因为程序跑的很快,很难找到开始运行出来的那一行),这时的缓冲区大小是4096个字节。
缓冲区解释
C语言的标准输入输出是分缓冲和无缓冲的。这里面缓冲分为全缓冲和行缓冲。
- 全缓冲: 全缓冲是指当缓冲区满了才进行 I/O 的读写操作。一般磁盘文件是全缓冲的(缓冲区一般为4096个字节)。
- 行缓冲: 行缓冲是指遇到换行符(即’\n’)后进行 I/O 操作,当然缓冲区满了也要进行操作。注意:换行符也被读入缓冲区。(缓冲区一般为1024个字节)
一般地,标准输入stdin
和标准输出stdout
为行缓冲,标准错误输出stderr
无缓冲。但是ANSI C要求下列缓存特征(参考APUE):
- 当且仅当标准输入和标准输出并不涉及交互作用设备时,它们才是全缓存的。
- 标准出错决不会是全缓存的。
但是,很多系统是这么实现的:
- 涉及到交互时,标准输入输出为行缓冲,否则为全缓冲
- 标准错误输出总是无缓冲
Unix中用宏_IO_LINE_BUF
和_IO_UNBUFFERED
(#include <stdio.h>
即可)来判断流属于哪个缓冲类型,判断方法(以stdin
举例)为:用stdin->_flags
与_IO_LINE_BUF
和_IO_UNBUFFERED
进行按为与运算,如果运算结果不为0,则为相应的缓冲类型;如果二者都为0,那么就是全缓冲。
下面验证之前的说明,即判断标准输入输出和标准错误输出的缓冲类型(以stdin
为例子,stdout
和stderr
也同理,有兴趣的同学自己验证):
/*
** 没有交互时,stdin的缓冲类型
*/
#include <stdio.h>
int main()
{
if (stdin->_flags & _IO_LINE_BUF) {
printf("stdin is Line-buf.\n");
} else if (stdin->_flags & _IO_UNBUFFERED) {
printf("stdin is Non-buf.\n");
} else {
printf("stdin is full-buf.\n");
}
return 0;
}
/*
** 有交互时,stdin的缓冲类型
*/
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
if (stdin->_flags & _IO_LINE_BUF) {
printf("stdin is Line-buf.\n");
} else if (stdin->_flags & _IO_UNBUFFERED) {
printf("stdin is Non-buf.\n");
} else {
printf("stdin is full-buf.\n");
}
return 0;
}