Linux之文件IO前世今生
在 Linux之文件系统前世今生(一) VFS中,我们提到了文件的读写,并给出了简要的读写示意图,本文将分析文件I/O的细节。

一、Buffered I/O(缓存I/O)& Directed I/O(直接I/O)
1.1、Page Cache
我们读写一个文件时,会从磁盘加载文件到内存中,以便我们快速读写文件;我们把内存中用于缓存文件的这块区域记为 Page Cache,Page Cache 位于内核态(所以也叫OS cache)。
- page 是内存管理分配的基本单位,
Page Cache由多个 page 构成;- page 在操作系统中通常为 4KB 大小,而
Page Cache的大小则为 4KB 的整数倍;- 更多 page 细节参见 Linux之内存管理前世今生(一)。
1.2、预读
根据程序的局部性原理,加载文件时除了加载文件指定位置内容,同时会加载该位置后续一部分连续内容到内存中,这个机制就是预读。所以 Page Cache 中额外包含了程序后续可能读写的内容。
1.2.1、Page Cache + 预读优势
- 加速数据访问
由于内存访问比磁盘访问快的多,且预读了后续数据;
- 提高系统磁盘I/O吞吐量
通过一次 I/O 将多个 page 装入
Page Cache能够减少磁盘 I/O 次数, 进而提高系统磁盘 I/O 吞吐量;
1.3、Write back(写回)& Write Through(写穿)
由于我们在内核态引入的Page Cache机制,所以我们对文件的读写都是基于Page Cache,但文件最终还是需要持久化到磁盘中去的。Linux 提供两种策略将Page Cache中 脏页(dirty page) 刷回磁盘:
Write back(写回)- 内核线程周期性地将脏页刷回磁盘,Linux 默认采用此策略 ;
- 该策略存在数据丢失的风险(比如遇到系统宕机、断电),理论上操作系统不宕机,数据就保证会刷回磁盘,即使用户程序崩溃;
Write Through(写穿)- 向用户层提供特定接口,应用程序可主动调用接口来直接刷新数据到磁盘;
- 以牺牲系统 I/O 吞吐量作为代价,向上层应用确保一旦写入,数据就已经落盘,不会丢失;
1.3.1、Page Cache刷盘涉及的系统调用
Write back(写回)& Write Through(写穿)这两种写策略均依赖系统调用,分为如下3种:
sync()将所有修改过的缓冲区排入写队列,然后就返回了,它并不等实际的写磁盘的操作结束。所以它的返回并不能保证数据的安全性。通常会有一个update系统守护进程每隔30s调用一次sync。
fsync(fd)- 将
fd代表的文件的脏数据和文件属性全部刷新至磁盘中; - 确保一直到写磁盘操作结束才会返回。数据库一般使用
fsync。
- 将
fdatasync(fd)- 将
fd代表的文件的脏数据刷新至磁盘,fdatasync的功能与fsync类似,但是仅仅在必要的情况下才会同步文件属性,因此可以减少一次IO写操作; - 举例来说,文件的尺寸(st_size)如果变化,是需要立即同步的,否则OS一旦崩溃,即使文件的数据部分已同步,由于文件属性没有同步,依然读不到修改的内容。而最后访问时间(atime)/修改时间(mtime)是不需要每次都同步的,只要应用程序对这两个时间戳没有苛刻的要求,基本无伤大雅。
- 将
1.3.2、Write back 刷盘时机
Page Cache脏页数量超过设定阈值;Page Cache脏页缓存超过设定缓存时间;- 应用程序主动刷盘,即调用
sync()、fdatasync(fd)、fsync(fd)三者任一; - 物理内存分配告警;
1.4、Buffered I/O(缓存I/O)& Directed I/O(直接I/O)
- 前面我们在内核态引入了
Page Cache用于加速文件I/O的操作就是 Buffered I/O(缓存I/O);
- 相反,如果在内核态关闭
Page Cache的使用(通过参数O_DIRECT),文件I/O直接与磁盘交互,我们称为Directed I/O(直接I/O)。
问题来了:Page Cache 这么好,什么场景需要关闭?
- Page Cache 位于内核态,对用户态提供的API灵活性差,用户态的应用程序无法对Page Cache 进行个性化定制,比如什么时间刷盘,刷哪些数据……
- Page Cache 容量受限,大文件读写时,很快会把Page Cache消耗完,导致之前缓存的常用的、热点数据被移出内存,下次访问热点数据时产生磁盘I/O,从而降低系统性能;即Page Cache 缓存的是小文件的热点数据。
- 举例:Mysql 中 InnoDB :
- Buffer Pool 关闭了Page Cache,即不在内核态缓存数据,直接在用户态缓存数据;
- redo log buffer 通过参数
innodb_flush_log_at_trx_commit(取值为0,1,2)设置为2来开启 Page Cache。
二、Blocking I/O(阻塞I/O)& Non Blocking I/O(非阻塞I/O)
- 前面我们从
Page Cache的维度,将 I/O分为 缓存I/O 和 直接I/O; - 接下来,我们从进程阻塞阶段的维度,将 I/O 分为 阻塞I/O 和 非阻塞I/O;
2.1、阻塞定义
阻塞 的主体是进程,当进程进入阻塞状态,是不占用CPU资源的。
2.2、阻塞时机
正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使当前进程由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,所以只有处于运行态(获得CPU)的进程,才可能将其转为阻塞状态。
2.3、阻塞I/O
由前面定义,I/O时期待的事件未发生,产生阻塞,那到底期待啥呢?
等待内核将数据准备好,换言之,等待 Page Cache 中有程序请求的数据。
以文件读取为例:当一个read操作发生时,它会经历两个阶段:
第一阶段:等待数据准备 (Waiting for the data to be ready)。
第二阶段:将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)。
2.3.1、阻塞I/O vs 非阻塞I/O
当应用程序发起read时,且Page Cache 中没有程序请求的数据时,内核会加载磁盘数据,若加载数据同时,
-
read调用立即返回告诉程序,数据没有准备好,这就是非阻塞I/O;
非阻塞 I/O 在I/O执行的第二个阶段仍然被阻塞了。
-
相反,内核闷声干活,直到数据加载完,并且数据从内核拷贝到应用程序中,才返回,这就是阻塞I/O。
阻塞 I/O 在I/O执行的两个阶段都被阻塞了。


三、同步 I/O(synchronous I/O)& 异步 I/O(asynchronous I/O)
POSIX(Portable Operating System Interface, 可移植操作系统接口)关于同步I/O和异步I/O的定义如下:
A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
An asynchronous I/O operation does not cause the requesting process to be blocked;

说人话就是,同步I/O会阻塞进程,异步I/O不会阻塞进程。
我们之前提到的 阻塞I/O 和 非阻塞I/O 都是同步I/O。
- 阻塞I/O 两个阶段都阻塞;
- 非阻塞I/O 第二个阶段阻塞;
四、小节
Page Cache的维度,将 I/O分为 缓存I/O 和 直接I/O;- 进程阻塞阶段的维度,将 I/O 分为 阻塞I/O 和 非阻塞I/O;
- 进程阻塞的维度,将 I/O 分为 同步I/O 和 异步I/O。
文件 I/O 至此基本介绍完毕,后续会介绍网络 I/O。
相关文章:
Linux之文件IO前世今生
在 Linux之文件系统前世今生(一) VFS中,我们提到了文件的读写,并给出了简要的读写示意图,本文将分析文件I/O的细节。 一、Buffered I/O(缓存I/O)& Directed I/O(直接I/O&#…...
Java中实现定时锁屏的功能(可以指定时间执行)
Java中实现定时锁屏的功能(可以指定时间执行) 要在Java中实现定时锁屏的功能,可以使用java.util.Timer或java.util.concurrent.ScheduledExecutorService来调度任务,并通过调用操作系统的命令来执行锁屏。下面我将给出一个基本的…...
半导体制造工艺讲解
目录 一、半导体制造工艺的概述 二、单晶硅片的制造 1.单晶硅的制造 2.晶棒的切割、研磨 3.晶棒的切片、倒角和打磨 4.晶圆的检测和清洗 三、晶圆制造 1.氧化与涂胶 2.光刻与显影 3.刻蚀与脱胶 4.掺杂与退火 5.薄膜沉积、金属化和晶圆减薄 6.MOSFET在晶圆表面的形…...
深入理解进程优先级
目录 引言 一、进程优先级基础 1.1 什么是进程优先级? 1.2 优先级与系统性能 二、查看进程信息 2.1 使用ps -l命令 2.2 PRI与NI的数学关系 三、深入理解Nice值 3.1 Nice值的特点 3.2 调整优先级实践 四、进程特性全景图 五、优化实践建议 结语 引言 在操…...
python中的flask框架
Flask 是一个用Python编写的轻量级Web应用框架 基于WSGI和Jinja2模板引擎 被称为“微框架”,其核心功能简单,不捆绑数据库管理、表单验证等功能,而是通过扩展来增加其他功能 Flask提供最基本的功能,不强制使用特定工具或库 通…...
微信小程序案例2——天气微信小程序(学会绑定数据)
文章目录 一、项目步骤1 创建一个无AppID的weather项目2 进入index.wxml、index.js、index.wxss文件,清空所有内容,进入App.json,修改导航栏标题为“中国天气网”。3进入index.wxml,进行当天天气情况的界面布局,包括温…...
【Linux网络编程】之守护进程
【Linux网络编程】之守护进程 进程组进程组的概念组长进程 会话会话的概念会话ID 控制终端控制终端的概念控制终端的作用会话、终端、bash三者的关系 前台进程与后台进程概念特点查看当前终端的后台进程前台进程与后台进程的切换 作业控制相关概念作业状态(一般指后…...
MarkupLM:用于视觉丰富文档理解的文本和标记语言预训练
摘要 结合文本、布局和图像的多模态预训练在视觉丰富文档理解(VRDU)领域取得了显著进展,尤其是对于固定布局文档(如扫描文档图像)。然而,仍然有大量的数字文档,其布局信息不是固定的࿰…...
了解AI绘图,Stable Diffusion的使用
AI绘图对GPU算力要求较高。 个人电脑配置可参考: CPU:14600kf 盒装 显卡:RTX 4080金属大师 OC,16G显存 主板:z790吹雪d4 内存:芝奇皇家戟4000c18,162G 硬盘:宏基gm7000 1T 散热:追风…...
jakarta EE学习笔记-个人笔记
WebServlet注解:声明一个类为Servlet Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented public interface WebServlet {// 指定Servlet的影子String name() default ""; // 匹配地址映射(URL)String[] value() default {};// …...
Kokoro 开源文本转语音引擎上线!多语言支持,无需联网,浏览器内极速运行
Kokoro 是一款轻量级的开源文本转语音(TTS)引擎,凭借其高效能和轻量化设计,迅速在技术社区中引起关注。本文将详细介绍 Kokoro 的主要特点,并提供在浏览器和 Python 环境中的代码示例,帮助您快速上手。 1. Kokoro:可在浏览器中运行的 TTS 引擎 1.1 简介 Kokoro 是一个…...
VSCode使用总结
1、VSCode左边资源窗口字体大小设置 方法一(使用,已成功) 进入安装目录Microsoft VS Code\resources\app\out\vs\workbench(如果是下载的压缩包,解压后resources\app\out\vs\workbench) 打开文件 workbench.desktop.main.css 搜…...
淘宝分类详情数据获取:Python爬虫的高效实现
在电商领域,淘宝作为中国最大的电商平台之一,其分类详情数据对于市场分析、竞争对手研究以及电商运营优化具有不可估量的价值。通过Python爬虫技术,我们可以高效地获取这些数据,为电商从业者提供强大的数据支持。 一、为什么选择…...
DeepSeek LLM 论文解读:相信长期主义开源理念可扩展大语言模型(DeepSeek 吹响通用人工智能的号角)
论文链接:DeepSeek LLM: Scaling Open-Source Language Models with Longtermism(相信长期主义开源理念可扩展大语言模型) 目录 摘要一、数据处理(一)数据清洗与丰富(二)分词器与词汇设置 二、模…...
嵌入式AI革命:DeepSeek开源如何终结GPU霸权,开启单片机智能新时代?
2025年,全球AI领域最震撼的突破并非来自算力堆叠的超级模型,而是中国团队DeepSeek通过开源策略,推动大模型向微型化、低功耗场景的跨越。相对于当人们还在讨论千亿参数模型的训练成本被压缩到600万美金而言,被称作“核弹级别”的操…...
【EPSG 坐标系系统完全解析(二)(万字详述)】
地理坐标系系统完全解析(万字详述) 第一章 坐标系基础理论(2000字) 1.1 地球空间参照系 1.1.1 地球椭球体模型 参考椭球参数对比: 椭球体长半轴(m)短半轴(m)使用国家/…...
fastchat 部署大模型
大模型实战--Llama3.1大模型部署及启动Web UI、OpenAI API实操 - 简书一、背景 随着人工智能技术的飞速发展,大模型(Large Language Models, LLMs)已成为自然语言处理领域的核心工具。这些模型以其强大的语言理解和生成能力,...ht…...
【安当产品应用案例100集】037-强化OpenVPN安全防线的卓越之选——安当ASP身份认证系统
在当前数字化时代,网络安全已成为企业发展的重要组成部分。对于使用OpenVPN的企业而言,确保远程访问的安全性尤为重要。安当ASP身份认证系统凭借其强大的功能和便捷的集成方式,为OpenVPN的二次登录认证提供了理想的解决方案,特别是…...
协议-ACLLite-ffmpeg
是什么? FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。 libavcodec是一个领先的音频/视频编解码器库&…...
树和二叉树_7
树和二叉树_7 一、leetcode-102二、题解1.引库2.代码 一、leetcode-102 二叉树的层序遍历 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 样例输入:root [3,9,20,null,nu…...
【C#】一维、二维、三维数组的使用
在C#中,数组是用于存储固定数量相同类型元素的数据结构。根据维度的不同,可以分为一维数组、二维数组(矩阵阵列)、三维数组等。每增加一个维度,数据的组织方式就会变得更加复杂。 一维数组 一维数组是最简单的数组形…...
Dubbo 3.x源码(30)—Dubbo Consumer服务调用源码(2)发起远程调用
基于Dubbo 3.1,详细介绍了Dubbo Consumer服务调用源码。 上文我们学习了,Dubbo 发起服务调用的上半部分源码,我们学习到了FailoverClusterInvoker最终会通过服务提供者Invoker#invoke发起RPC调用,下面我们来学习Dubbo 发起服务调用…...
学习日记-250207
一.论文 1.Prompt Learning for News Recommendation 任务不一致(LLM与实际任务)产生prompt提示。 Prompt Learning for News Recommendation 论文阅读 SIGIR2023-CSDN博客 2.GPT4Rec: A Generative Framework for Personalized Recommendation and…...
Rocky Linux9安装Zabbix7.0(精简版)
Linux 系统版本 Rocky Linux release 9.3 (Blue Onyx) 注意:zabbix 7以上版本不支持CentOS 7系统,需要CentOS 8以上, 本教程支持CentOS9及Rocky Linux 9 在Rocky Linux release 9.3测试通过 Linux环境准备 关闭防火墙和selinux #关闭防…...
网络分析工具—WireShark的安装及使用
Wireshark 是一个广泛使用的网络协议分析工具,常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议,能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析: …...
C++开发(软件开发)常见面试题
目录 1、C里指针和数组的区别 2、C中空指针请使用nullptr不要使用NULL 3、http/https区别和头部结构? 4、有了mac地址为什么还要ip地址?ip地址的作用 5、有了路由器为什么还要交换机? 6、面向对象三大特性 7、友元函数 8、大端小端 …...
云原生后端|实践?
云原生(Cloud Native)是一种构建和运行应用程序的方法,它充分利用云计算的优势,包括弹性、可扩展性、高可用性和自动化运维。云原生后端开发通常涉及微服务架构、容器化、持续集成/持续部署(CI/CD)、服务网…...
WEB攻防-文件下载文件读取文件删除目录遍历目录穿越
目录 一、文件下载漏洞 1.1 文件下载案例(黑盒角度) 1.2 文件读取案例(黑盒角度) 二、文件删除 三、目录遍历与目录穿越 四、审计分析-文件下载漏洞-XHCMS 五、审计分析-文件读取漏洞-MetInfo-函数搜索 六、审计分析-…...
to_csv保存指定列的方法
df是DataFrame的数据,它的列为[代码, 名称, 最高, 最低] 现在我只想将‘代码’、“名称”两列内容存入csv,实现如下: columns_to_save [代码, 名称] df.代码 df.代码.apply("{}".format)#此行可以防止代码之前的0被忽略掉 d…...
MySQL数据库(七)SQL 优化
一 插入数据 采用方法 1 批量插入 2 手动提交事务 3 主键顺序插入 4* 使用load插入指令数据 二 主键优化 1 数据组织方式 在InnoDB存储引擎中,表中的数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表 2 页分裂 页可以为空也可…...


