糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 数据缓冲策略 —— 无缓冲 行缓冲 全缓冲(缓冲区大小测试)

数据缓冲策略 —— 无缓冲 行缓冲 全缓冲(缓冲区大小测试)

时间:2020-07-01 16:22:40

相关推荐

数据缓冲策略 —— 无缓冲 行缓冲 全缓冲(缓冲区大小测试)

printf打印数据时,一般会先把数据放入C缓冲区,然后再刷新到内核缓冲区,最后再写入硬件

这个过程中,数据从C缓冲区迁移到内核缓冲区的操作我们称为缓冲(也可以理解为刷新)

下面我们将介绍 缓冲策略的三种情况

1、无缓冲(不刷新),如write

2、行缓冲(行刷新),遇到换行符\n才会刷新

3、全缓冲(缓冲区满了才刷新),如写入数据到磁盘

目录

一、无缓冲(不刷新)

1、无缓冲验证

2、验证结果

二、行缓冲

1、不加 '\n' 验证

2、添加 '\n' 验证

三、全缓冲

1、打印少量的数据

2、打印大量的数据

3、缓冲区大小验证

四、缓冲案例:行缓冲 变成了 全缓冲

1、案例介绍

2、案例分析

一、无缓冲(不刷新)

不缓冲的意思就是,不会向内核缓冲区存入内容,而是直接输出到文件中,比如系统调用函数 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) 断开了内核缓冲区和磁盘文件之间的联系,这就导致数据永远留在了内核缓冲区。

如果觉得《数据缓冲策略 —— 无缓冲 行缓冲 全缓冲(缓冲区大小测试)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。