缓冲区与setvbuf函数

缓冲区

该笔记适用于Ubuntu,在Windows或其它平台上可能会存在不同。

什么是缓冲?

缓冲区又称为缓存,它是内存空间的一部分,用来缓冲输入或输出的数据。

为什么要引入缓冲区呢?

比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作远快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度

​ 缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

缓冲区的类型

缓冲区分为三种类型:全缓冲行缓冲不缓冲

1、全缓冲

在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2、行缓冲

在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

3、不缓冲

也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

缓冲区的刷新

下列情况会引发缓冲区的刷新:

  1. 缓冲区满时;

  2. 执行fflush函数;

  3. 正常关闭文件。

  4. 正常退出程序或进程。

  5. 行缓冲遇到 \n刷新。

如何改变缓存类型

这里只展示setvbuf函数的使用,定义流stream应如何缓冲。

//与缓冲区相关的一些函数
#include <stdio.h>
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);
参数:
stream:这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。
buffer:这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。
mode: 这指定了文件缓冲的模式:_IOFBF、_IOLBF、_IONBF。
size:这是缓冲的大小,以字节为单位。
返回值:
如果成功,则该函数返回 0,否则返回非零值。
模式描述
_IOFBF全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
_IOLBF行缓冲:对于输出,数据在遇到换行符或者在缓冲填满时被写入,具体视情况而定。对于输入,缓冲会在请求输入且缓冲为空时被填充,直到遇到下一个换行符。
_IONBF无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略,即在无缓存模式,即使设置了缓冲区也不会用到。

验证

先来对比VScode 和Ubun中缓冲的表现形式

2 .

9.

(截图有点多😂,主要为了我以后复习方便一点,望见谅)

从以上10个测试可以得到结论:(不同平台不同的编译器得到的结果可能不一样)

  • VScode中的stdout属于无缓冲类型
  • Ubuntu中的stdout属于行缓冲类型(行缓冲遇到换行符会清空缓冲区,而全缓冲不会)

注意:缓冲区的大小选择1024(不管用默认的还是自己定义的),我试过用100字节大小的缓冲区,导致结果不一样,具体情况可能与stdout内部的实现规则有关,知道原因的朋友欢迎留言。

以下结论测试截图就不发出来了,感兴趣的可以自己测一下

  • 当按下Ctrl+C强行中断程序时,VScode会将缓冲区中的剩余内容刷出,而Ubuntu不会;

    比如在Ubuntu中中打开文件进行写数据时(存在缓冲区的情况),如果中途强行Ctrl +C,由于没有关闭文件而且Ubuntu不会刷新缓冲区,会导致尚在缓冲区中的内容没有写入到文件中;而在VScode上,强行终端后输入的数据还是会写入到文件中。

  • printf函数在Ubuntu的特点(VScode没有)(仅仅是对于行缓冲):

    1. 遇到换行符时会刷新缓冲区

    2. 遇到getchar()、scanf()这种需要输入数据的函数时会刷新缓冲区

验证setvbuf函数

  • 当缓冲区满的时候会刷新缓冲区
  • 当设为无缓冲时,所设置的缓冲区会被忽略

由于还不清楚stdout的源码是如何实现功能的,在VS和Ubuntu上验证缓冲区满是刷新缓冲区输出的内容方面还存在一些疑问,上面的截图只是刚好满足而已,后续如果了解原因会进行更新。

参考资料

>>缓冲区与缓存

>>什么是缓冲区

其它笔记

>>变参函数

>>Markdown学习笔记

>>数据在内存中的存储

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值