函数fread是否采用全缓冲模式?其全缓冲工作原理探究
fread与全缓冲模式的原理解析
1. fread的缓冲模式由谁决定?
fread本身不直接设置缓冲模式,它的行为完全依赖于所操作的FILE流的缓冲属性。默认规则是:
- 针对磁盘文件的FILE流(比如
fopen打开的普通文件),标准库默认采用全缓冲模式; - 终端类设备(如stdin、stdout)通常是行缓冲或无缓冲,具体由系统和标准库实现决定。
2. 全缓冲模式的工作逻辑(以fread为例)
全缓冲的核心目的是减少用户态与内核态的切换开销,靠一块内存缓冲区实现批量IO:
- 当调用
fread时,标准库先检查当前FILE流的用户态缓冲区:- 如果缓冲区里还有未被读取的数据,直接从这里拷贝数据到你提供的目标缓冲区,全程不触发系统调用;
- 如果缓冲区为空,标准库会发起一次性批量读取(通常是缓冲区的大小,比如4KB、8KB,具体由标准库和系统决定),把数据从磁盘读到内核缓冲区,再拷贝到FILE流的用户态缓冲区,之后再从这个缓冲区取数据给你。
- 对应写入操作(比如
fwrite)的逻辑类似:先把数据攒在用户态缓冲区,直到缓冲区满,才一次性刷到内核缓冲区,最终由内核决定何时写入磁盘。
3. fread是不是只在缓冲区满时才读取数据?
当然不是,除了缓冲区被读空触发新的读取外,这些场景也会触发磁盘读取:
- 首次调用
fread时,缓冲区是空的,不管你要读多少字节,都会触发一次批量读取; - 调用
fflush、fseek、fclose这类操作时,会强制重置缓冲区状态,后续的fread会重新从磁盘加载数据; - 当文件已经读到末尾时,即使缓冲区没被填满,也会把剩余的有效数据返回给你。
举个实际原理场景:假设FILE流的全缓冲大小是4KB,第一次调用fread请求100字节,此时缓冲区为空,标准库会一次性读4KB到缓冲区,然后给你拷贝100字节;第二次再调用fread要100字节,直接从缓冲区剩下的3996字节里拿,不用碰磁盘;直到缓冲区的数据被读完,才会再次发起磁盘读取。
内容的提问来源于stack exchange,提问作者appled
相关产品推荐
相关产品推荐

