当前位置: 首页 > article >正文

Linux的缓存I/O和无缓存IO

一、I/O缓存的背景

I/O缓存是指在内存里开辟一块区域,存放用来接收用户输入和用于计算机输出的数据,以减小系统开销和提高外设效率。linux对IO文件的操作分为不带缓存的IO操作和带缓存的IO操作(标准IO操作)。为什么存在C标准I/O库函数与Unbuffered I/O函数?它们有什么区别?

二、带缓存的I/O操作

​带缓存IO(标准IO),不依赖系统内核,所以移植性强,使用标准IO操作为了减少对read()和write()的系统调用次数,带缓存IO其实就是在用户层再建立一个缓存区,这个缓存区的分配和优化长度等其他细节都是标准IO库代你处理好了。系统调用如图所示

比如要写数据到文件上,内核缓存区长度是100字节,我们调用不带缓存的IO函数write()就要调用10次,这样系统效率低。

现在我们在用户层建立另一个缓存区(用户层缓存区或者叫流缓存),假设流缓存的长度是50字节,我们用标准C库函数的fwrite()将数据写入到这个流缓存区里面,流缓存区满50字节后在进入内核缓存区,此时再调用系统函数write()将数据写入到文件(实质是磁盘)上标准IO操作fwrite()最后还是要掉用无缓存IO操作write,这里进行了两次调用fwrite()写100字节也就是进行两次系统调用write()函数。

​ 无缓存IO操作数据流向路径:数据——内核缓存区——磁盘
​ 标准IO操作数据流向路径:数据——流缓存区——内核缓存区——磁盘

​ 标准I/O对每个I/O流自动进行缓存管理(标准I/O函数通常调用malloc来分配缓存)。它提供了三种类型的缓存:
​ 1) 全缓存:缓存满时I/O操作。磁盘上的文件通常是全缓存的。
​ 2)行缓存。当输入输出遇到新行符或缓存满时.stdin、stdout通常是行缓存的。
​ 3)无缓存。相当于read、write了。stderr通常是无缓存的

三、无缓存I/O(Unbuffered )I/O函数

刚看到这个"unbuffered",读者就觉得奇怪,操作系统不是对所有的输入输出都会做缓存吗(delayed write),为什么还会存在unbuffered?

其实,这里的ubuffered,是指的是针对与read和write本身来说,它们是没有缓存机制,比如read(fd,temp,100),在读够100个字节后或者遇到文件EOF后就返回,非常单纯。而C标准库函数中的fread和fwrite,就是利用缓存技术来调用read和write,可以说是buffered I/O。

但是,叫做无缓存IO是因为在用户层没有缓存,但对于Linux内核来说,还是进行了缓存,只是用户层看不到罢了。

这些不带缓存的I/O函数不是标准 C的组成部分,但是,它们是POSIX.1和Single UNIX Specification的组成 部分。C标准库函数是C标准的一部分,而Unbuffered I/O函数是UNIX标准的一部分。只有在UNXI平台上才能用Unbuffered I/O函数,windows上不行。所以C标准I/O库函数在头文件stdio.h中声明,而read、 write等函数在头文件unistd.h中声明。
 

四、两种I/O函数使用场景

open、read、write、close等系统函数称为无缓冲I/O(Unbuffered I/O)函数,用户程序在读写文件时既可以调用C标准I/O库函数,也可以直接调用底层的Unbuffered I/O函数,那个各自使用场景是什么呢?

  • 用Unbuffered I/O函数每次读写都要进内核,调一个系统调用比调一个用户空间的函数要慢很多,所以在用户程序开辟I/O缓冲区还是必要的,用C标准I/O库函数比较方便,省去自己开辟内存空间。
  • 用C标准I/O库函数要时刻注意I/O缓冲区和实际文件有可能不一致,在必要时调用fflush(3)。
  • UNIX的传统是Everything is a file,I/O函数不仅可以读写文件还可以读写设备。在读写设备时通常是不希望有缓冲的。比如网络设置的读写就希望是实时读写,而不希望只写到缓冲区里,所以网络编程通常直接调用Unbuffered I/O函数。
     

五、磁盘交互的读写文件流程

当应用程序尝试读取磁盘上的某块数据的时候,如果这块数据已经存放在页缓存(内核高速缓存)中,那么这块数据就可以立即返回给应用程序,而不需要经过实际的物理读盘操作。当然,如果数据在应用程序读取之前并未被存放在页缓存中),那么就需要先将数据从磁盘读到页缓存中去。

对于写操作来说,应用程序也会将数据先写到页缓存中去(这里所说的写到页缓存中,如果是调用标准库I/O进行写,那么首先是写到标准库的缓冲区内,如果标准库的缓冲区写满以后,在写到页缓冲内;如果是系统调用,那么直接写到页缓冲内)。

数据是否被立即写到磁盘上去取决于应用程序所采用的写操作机制:如果用户采用的是同步写机制,那么数据会立即被写回到磁盘上,应用程序会一直等到数据被写完为止;如果用户采用的是延迟写机制,那么应用程序就完全不需要等到数据全部被 写回到磁盘,数据只要被写到页缓存中去就可以了。

在延迟写机制的情况下,操作系统会定期地将放在页缓存中的数据刷到磁盘上。与异步写机制不同的是,延迟写机制在数据完全写到磁盘上得时候不会通知应用程序,而异步写机制在数据完全写到磁盘上得时候是会返回给应用程序的。所以延迟写机制本省是存在数据丢失的风险的,而异步写机制则不会有这方面的担心。

 

参考:

带缓冲I/O 和不带缓冲I/O的区别与联系-CSDN博客

理解标准I/O库的缓冲机制及应用-CSDN博客

unix系统编程小结(一)------文件I/O-neilhappy-ChinaUnix博客


 


http://www.kler.cn/a/569060.html

相关文章:

  • macOS - 使用 tmux
  • React核心知识及使用场景
  • 对大模型输出的 logits 进行处理,从而控制文本的生成
  • 【人工智能】GPT-4 vs DeepSeek-R1:谁主导了2025年的AI技术竞争?
  • RocketMQ启动教程
  • Docker项目部署-部署前端
  • 一个基于C# Winform开源免费的通用快速开发框架,内置完整的权限架构!
  • 晶圆搬运真空机械臂概述
  • 【Elasticsearch】节点设置(Node Settings)是用于定义和管理集群中每个节点的行为和角色的关键配置
  • UE5切换关卡函数OpenLevel,输入模式结构体,UI界面
  • Vue.js 测试 Vue 3 Composition API
  • SQL Server 数据库管理工具的安装以及使用
  • C++数据结构之数组(详解)
  • SpringMVC学习(初识与复习Web程序的工作流程)(1)
  • 浅谈Linux中的软件包管理器——基于ubuntu环境
  • C++二分图
  • 鸿蒙(OpenHarmony/HarmonyOS)开发中常用的命令行工具及操作大全
  • 基于大数据的民宿旅馆消费数据分析系统
  • 0.2S级高精度物联网电能表技术参数介绍
  • 【每日学点HarmonyOS Next知识】全局调整字体、h5选择框无法取消选中、margin不生效、Length转换为具体值、Prop和link比较