printf打印数据时,一般会先把数据放入C缓冲区,然后再刷新到内核缓冲区,最后再写入硬件
这个过程中,数据从C缓冲区迁移到内核缓冲区的操作我们称为缓冲(也可以理解为刷新)
下面我们将介绍 缓冲策略的三种情况
1、无缓冲(不刷新),如write
2、行缓冲(行刷新),遇到换行符\n才会刷新
3、全缓冲(缓冲区满了才刷新),如写入数据到磁盘
目录
一、无缓冲(不刷新)
不缓冲的意思就是,不会向内核缓冲区存入内容,而是直接输出到文件中,比如系统调用函数 write函数
1、无缓冲验证
下面用一段简单的代码来验证这一现象,基本思路是:调用write函数向文件里写入内容,使用死循保证当前进程不会退出(退出的时候会刷新缓冲区)。新开一个终端查看文件内容,如果文件中包含了写入的内容,说明是无缓冲;如果不包含写入的内容,说明是其他缓冲。
测试代码如下:
int main(int argc, char** argv){
int fd = open("./1.txt",O_WRONLY | O_APPEND);
const char* buf = "hello, world";
write(fd, buf, strlen(buf)); // 注意这里使用的是strlen,而不是sizeof
// sizeof(buf) 就会变成计算buf指针的大小,那就是固定4个字节
while(1)
{
sleep(1000);
}
close(fd);
return 0;
}
2、验证结果
验证结果如下:
我们发现, 进程还没有退出的情况下,字符串就已经被写入到文件里了,说明write函数没有经过内核缓冲区,直接将数据写入到文件中。
二、行缓冲
行缓冲的意思是,遇到换行符的时候才会将数据从内核缓冲区刷新到 磁盘文件。最典型的就是printf 函数,printf函数中如果不加 ‘\n’,那就只是全缓冲,如果遇到了‘\n’,此时会立马将数据刷新到 stdout 流。
1、不加 ‘\n’ 验证
验证的基本思路:不加‘\n’,同时不让进程退出,如果printf 可以打印内容,说明不是行缓冲;如果不行,可以看一下接下来的添加 ‘\n’ 验证。测试代码如下:
int main(int argc, char** argv){
printf("hello, world"); // 不加'\n'
while(1)
{
sleep(1000);
}
close(fd);
return 0;
}
此时printf 并没有打印内容,说明此时数据很有可能还留在内核缓冲区里。
2、添加 ‘\n’ 验证
验证的基本思路:如果加了’\n’以后,可以看到打印的内容,说明是行缓冲;如果没有,说明是其他缓冲。
int main(int argc, char** argv){
printf("hello, world\n"); // 加'\n'
while(1)
{
sleep(1000);
}
close(fd);
return 0;
}
三、全缓冲
全缓冲的意思是,只有等缓冲区满了以后,才会将内核缓冲区里的数据刷新到磁盘文件。printf函数在没有加 ‘\n’ 的时候就是典型的 全缓冲。我们可以通过打印少量的数据、打印大量的数据来验证。
1、打印少量的数据
此时我们只输出 20 个字符看一下是否会打印出来。
int main(int argc, char** argv){
for(int i = 0; i < 20; i++)
{
printf("x");
}
while(1)
{
sleep(1000);
}
close(fd);
return 0;
}
从这里可以看出,缓冲区的大小是大于 20 个字节的。
2、打印大量的数据
此时我们改为输出 2000 个字符来看一下是否会打印。
int main(int argc, char** argv){
for(int i = 0; i < 2000; i++)
{
printf("x");
}
while(1)
{
sleep(1000);
}
close(fd);
return 0;
}
从这里可以看出,缓冲区的大小是小于 2000 的,那么缓冲大小到底有多少呢?
3、缓冲区大小验证
可以算一下图中打印了多少个’x’,我们使用在线字符统计工具看一下。正好是 1K
四、缓冲案例:行缓冲 变成了 全缓冲
1、案例介绍
test.c 的代码如下
然后我们在命令行里输入
2、案例分析
(1) 11行~16行:printf函数运行
——》每运行一行printf,数据会先存入C缓冲区,遇到\n,立即刷新到文件内核缓冲区, 这个是行刷新(行缓冲),正准备刷新的时候发现了重定向符号 ‘ > ’
——》重定向符号 ‘ > ’ 断开原本的fd = 1 和 stdout之间的关系,然后指向 log.txt(向磁盘文件写入内容是全缓冲)
——》结果行缓冲 变成了 全缓冲(这就导致 I/O缓冲区的内容不会立即刷新)
行缓冲:遇到\n立即刷新C缓冲区,即 把C缓冲区的内容迁移到内核缓冲区
全缓冲:等C缓冲区满了再刷新到内核缓冲区,即暂不迁移
到这一步,打印的内容不会输出到stdout文件,或者log.txt 文件,而是留在了内核缓冲区里。此时又因为调用了 close(1),close(1) 断开了内核缓冲区和磁盘文件之间的联系,这就导致数据永远留在了内核缓冲区。
今天的文章数据缓冲策略 —— 无缓冲、行缓冲、全缓冲(缓冲区大小测试)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31113.html