read 文件一个字节实际会发生多大的磁盘IO?

Qos介绍及功能->分类标记->流量管理(令牌桶)->拥塞管理与拥塞避免 Qos介绍及功能->分类标记->流量管理(令牌桶)->拥塞管理与拥塞避免 阅读详情

在日常开发中一些看似司空见惯的问题上,我觉得可能大多数人其实并没有真正理解,或者理解的不够透彻。不信我们来看以下一段简单的读取文件的代码:

图片

上图中的代码仅仅只是对某个文件读取了一个字节,基于这个代码片段我们来思考:

  • 1、读取文件 1 个字节是否会导致磁盘 IO ?

  • 2、如果发生了磁盘 IO,那发生的是多大的 IO 呢?

大家平时用的各种语言 C++、PHP、Java、Go 啥的封装层次都比较高,把很多细节都给屏蔽的比较彻底。如果想把上面的问题搞清楚,需要剖开 Linux 的内部来看 Linux 的 IO 栈。

一、大话 Linux IO 栈

废话不多说,我画了一个 Linux IO 栈的简化版本。

图片

通过 IO 栈可以看到,我们在应用层简单的一次 read 而已,内核就需要 IO 引擎、VFS、PageCache、通用块管理层、IO 调度层等许多个组件来进行复杂配合才能完成。

那这些组件都是干啥的呢?我们挨个简单过一遍。不想看这个的同学可以直接跳到第二节的读文件读过程。

1.1 IO 引擎

开发同学想要读写文件的话,在 lib 库层有很多套函数可以选择,比如 read & write,pread & pwrite。这事实上就是在选择 Linux 提供的 IO 引擎。

常见的 IO 引擎种类如下:

图片

我们开篇中代码片用的 read 函数就属于 sync 引擎。IO 引擎仍然处于上层,它需要内核层的提供的系统调用、VFS、通用块层等更底层组件的支持才能实现。

接着让我们继续深入到内核,来介绍各个内核组件。

1.2 系统调用

当进入到系统调用以后,也就进入到了内核层。

系统调用将内核中其它组件的功能进行封装,然后通过接口的形式暴露给用户进程来访问。

图片

对于我们的读取文件的需求,系统调用需要依赖 VFS 内核组件。

1.3 VFS 虚拟文件系统

VFS 的思想就是在 Linux 上抽象一个通用的文件系统模型,对我们开发人员或者是用户提供一组通用的接口,让我们不用 care 具体文件系统的实现。VFS 提供的核心数据结构有四个,它们定义在内核源代码的 include/linux/fs.h 和 include/linux/dcache.h 中。

图片

  • superblock:Linux 用来标注具体已安装的文件系统的有关信息。

  • inode:Linux 中的每一个文件/目录都有一个 inode,记录其权限、修改时间等信息。

  • desty:目录项,是路径中的一部分,所有的目录项对象串起来就是一棵 Linux 下的目录树。

  • file:文件对象,用来和打开它的进程进行交互。

围绕这这四个核心数据结构,VFS 也都定义了一系列的操作方法。比如,inode 的操作方法定义 inode_operations,在它的里面定义了我们非常熟悉的 mkdir 和 rename 等。对于 file 对象,定义了对应的操作方法 file_operations ,如下:

// include/linux/fs.h
struct file {
    ......
    const struct file_operations    *f_op
}
struct file_operations {
    ......
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
            ......
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *, fl_owner_t id);
}

注意 VFS 是抽象的,所以它的 file_operations 里定义的 read、write 都只是函数指针, 实际中需要具体的文件系统来实现,例如 ext4 等等。

1.4 Page Cache

Page Cache。它的中文译名叫页高速缓存。它是 Linux 内核使用的主要磁盘高速缓存,是一个纯内存的工作组件。Linux 内核使用搜索树来高效管理大量的页面。

有了它,Linux 就可以把一些磁盘上的文件数据保留在内存中,然后来给访问相对比较慢的磁盘来进行访问加速。

当用户要访问的文件的时候,如果要访问的文件 block 正好存在于 Page Cache 内,那么 Page Cache 组件直接把数据从内核态拷贝到用户进程的内存中就可以了。如果不存在,那么会申请一个新页,发出缺页中断,然后用磁盘读取到的 block 内容来填充它 ,下次直接使用。

图片

看到这里,开篇的问题可能你就明白一半了,如果你要访问的文件近期访问过,那么 Linux 大概率就是从 Page cache 内存中的拷贝给你就完事,并不会有实际的磁盘 IO 发生。

不过有一种情况下,Pagecache 不会生效, 那就是你设置了 DIRECT_IO 标志。

1.5 文件系统

Linux 下支持的文件系统有很多,常用的有 ext2/3/4、XFS、ZFS 等。

要用哪种文件系统是在格式化的时候指定的。因为每一个分区都可以单独进行格式化,所以一台 Linux 机器下可以同时使用多个不同的文件系统。

图片

文件系统里提供对 VFS 的具体实现。除了数据结构,每个文件系统还会定义自己的实际操作函数。例如在 ext4 中定义的 ext4_file_operations。在其中包含的VFS中定义的 read 函数的具体实现:do_sync_read 和 do_sync_write。

图片

const struct file_operations ext4_file_operations = {
    .llseek         = ext4_llseek,
    .read           = do_sync_read,
    .write          = do_sync_write,
    .aio_read       = generic_file_aio_read,
    .aio_write      = ext4_file_write,
    ......
}

和 VFS 不同的是,这里的函数就是实实在在的实现了。

1.6 通用块层

文件系统还要依赖更下层的通用块层。

对上层的文件系统,通用块层提供一个统一的接口让供文件系统实现者使用,而不用关心不同设备驱动程序的差异,这样实现出来的文件系统就能用于任何的块设备。通过对设备进行抽象后,不管是磁盘还是机械硬盘,对于文件系统都可以使用相同的接口对逻辑数据块进行读写操作。

对下层。I/O 请求添加到设备的 I/O 请求队列。它定义了一个叫 bio 的数据结构来表示一次 IO 操作请求(include/linux/bio.h)

1.7 IO 调度层

当通用块层把 IO 请求实际发出以后,并不一定会立即被执行。因为调度层会从全局出发,尽量让整体磁盘 IO 性能最大化。

对于机械硬盘来说,调度层会尽量让磁头类似电梯那样工作,先往一个方向走,到头再回来,这样整体效率会比较高一些。具体的算法有 deadline 和 cfg ,算法细节就不展开了,感兴趣同学可以自行搜索。

对于固态硬盘来说,随机 IO 的问题已经被很大程度地解决了,所以可以直接使用最简单的 noop 调度器。

在你的机器上,通过dmesg | grep -i scheduler来查看你的 Linux 支持的调度算法。

图片

通用块层和 IO 调度层一起为上层文件系统屏蔽了底层各种不同的硬盘、U盘的设备差异。

二、读文件过程

我们已经把 Linux IO 栈里的各个内核组件都简单介绍一遍了。现在我们再从头整体过一下读取文件的过程(图中源代码基于 Linux 3.10)

图片

这一张长图把整个 Linux 读取文件的过程都串了一遍。

三、回顾开篇问题

回到开篇的第一个问题:读取文件 1 个字节是否会导致磁盘 IO ?

从上述流程中可以看到,如果 Page Cache 命中的话,根本就没有磁盘 IO 产生。

所以,大家不要觉得代码里出现几个读写文件的逻辑就觉得性能会慢的不行。操作系统已经替你优化了很多很多,内存级别的访问延迟大约是 ns 级别的,比机械磁盘 IO 快了好几个数量级。如果你的内存足够大,或者你的文件被访问的足够频繁,其实这时候的 read 操作极少有真正的磁盘 IO 发生。

假如 Page Cache 没有命中,那么一定会有传动到机械轴上进行磁盘 IO 吗?

其实也不一定,为什么,因为现在的磁盘本身就会带一块缓存。另外现在的服务器都会组建磁盘阵列,在磁盘阵列里的核心硬件Raid卡里也会集成RAM作为缓存。只有所有的缓存都不命中的时候,机械轴带着磁头才会真正工作。

再看开篇的第二个问题:如果发生了磁盘 IO,那发生的是多大的 IO 呢?

如果所有的 Cache 都没有兜住 IO 读请求,那么我们来看看实际 Linux 会读取多大。真的按我们的需求来,只去读一个字节吗?

整个 IO 过程中涉及到了好几个内核组件。而每个组件之间都是采用不同长度的块来管理磁盘数据的。

  • Page Cache 是以页为单位的,Linux 页大小一般是 4KB

  • 文件系统是以块(block)为单位来管理的。使用 dumpe2fs 可以查看,一般一个块默认是 4KB

  • 通用块层是以段为单位来处理磁盘 IO 请求的,一个段为一个页或者是页的一部分

  • IO 调度程序通过 DMA 方式传输 N 个扇区到内存,扇区一般为 512 字节

  • 硬盘也是采用“扇区”的管理和传输数据的

可以看到,虽然我们从用户角度确实是只读了 1 个字节(开篇的代码中我们只给这次磁盘IO留了一个字节的缓存区)。但是在整个内核工作流中,最小的工作单位是磁盘的扇区,为512字节,比1个字节要大的多。

另外 block、page cache 等高层组件工作单位更大。其中 Page Cache 的大小是一个内存页 4KB。所以一般一次磁盘读取是多个扇区(512字节)一起进行的。假设通用块层 IO 的段就是一个内存页的话,一次磁盘 IO 就是 4 KB(8 个 512 字节的扇区)一起进行读取。

另外我们没有讲到的是还有一套复杂的预读取的策略。所以,在实践中,可能比 8 更多的扇区来一起被传输到内存中。

最后,啰嗦几句

操作系统的本意是做到让你简单可依赖, 让你尽量把它当成一个黑盒。你想要一个字节,它就给你一个字节,但是自己默默干了许许多多的活儿。

我们虽然国内绝大多数开发都不是搞底层的,但如果你十分关注你的应用程序的性能,你应该明白操作系统的什么时候悄悄提高了你的性能,是怎么来提高的。以便在将来某一个时候你的线上服务器扛不住快要挂掉的时候,你能迅速找出问题所在。

想继续深入学习的同学可以参考《深入理解 Linux 内核》之第十四章。

标准IO与文件IO linux下文件操作包含下面4个头文件: 阅读详情

相关推荐

Qos--令牌桶技术介绍

令牌桶技术介绍,主要介绍meter的原理,以及同模式(2697、2698等)两桶之间的关系

Linux中的文件IO与标准IO以及文件描述符表和缓冲区详解

IO既是输入input和输出output的首字母缩写形式,文件则是一组相关数据的有序集合,即文件IO就是有序数据流相对于计算机的输入与输出(一般来说我们是站在计算机的角度去描述),它描述的是计算机数据流动的过程。所以学习IO可以让我们理解数据的流动,以及正确的控制数据的流动。文件描述符表则是用来管理数据的输入输出,对应的文件描述符则可以找到文件的入口进行管理。

2301_77005503的博客 597

QoS技术中令牌桶算法实现方式比较

QoS技术中令牌桶算法实现方式比较,关于QoS令牌桶应用的算法。

系统试图将驱动器合并到合并驱动器上的目录_系统设计那些事儿:硬盘 I/O

数据库系统总会涉及非易失性存储,我们需要知道一个典型的计算机系统是如何进行存储管理的。时至今日,虽然 SSD 已经成为很多数据库管理员的选择,但传统 HDD 还是有着广泛的应用,文件系统和存储引擎大部分设计和发展还是基于 HDD 的行为;过去数十年来,HDD 一直是计算机系统中持久存储的主要形式。本文回顾硬盘的物理特性,硬盘的主要性能指标,以及操作是如何进行硬盘 I/O 性能优化的,最后参考开源系...

weixin_39650784的博客 918

服务器基础知识介绍

服务器,不仅仅是一台高性能计算机,更是网络的核心节点,承担着网络服务的责任。然而,相较于普通计算机,服务器对于稳定性、安全性和性能等方面提出了更高的要求,这使得它们在数字化浪潮中傲然独立。在硬件成本结构中,CPU和芯片组占据约50%的成本,内存占15%,外部存储占10%,其余硬件约占25%。服务器的逻辑结构与普通计算机相似,但由于其需要提供高性能计算,对稳定性、可靠性、安全性、可扩展性和可管理性的要求更高。服务器的分类多种多样,根据产品形式可分为塔式服务器、机架服务器、刀片服务器和机柜服务器。

m0_73576645的博客 1879

rockchip rk3566 android11 网口log报错: DMA engine initialization failed

问题描述:上电初始化前将网口插入,然后上电初始化网口能够正常使用,且能够找到PHY,ifconfig 查看能够有eth0 产生,网口正常使用且能够热插拔,但上电初始化时,不插入网口,就会报DMA engine initialization failed 错误,DMA 初始化的时候出错了。 分析:一般产生这个问题可以认为是GMAC 的工作时钟出问题了。先测量时钟引脚是否有时钟,时钟频率以及幅度等指标是否正常,主要确认以下几个方面: 1.IOMUX 出错,检查时钟脚寄存器值是否正确。 2.时钟方向以及配置

qq_48709036的博客 2万+

QoS服务质量二令牌桶算法及QoS业务分类

令牌桶算法在能够限制数据的平均传输速率外,还允许某种程度的突发传输。令牌算法是以固定速度往一个桶内增加令牌,当桶内令牌满了后,就停止增加令牌。上游请求时,先从桶里拿一个令牌,后端只服务有令牌的请求,所以后端处理速度不一定是匀速的。当有突发请求过来时,如果令牌桶是满的,则会瞬间消耗桶中存量的令牌。如果令牌还不够,那么再等待发放令牌(固定速度),这样就导致处理请求的速度超过发放令牌的速度。.....................

weixin_42227328的博客 3118

Windows 2000系统下载与全套镜像安装:从镜像校验到驱动兼容性实战指南

操作系统镜像文件是安装系统的核心载体,其完整性直接影响部署成败。哈希校验作为验证文件一致性的基础手段,能有效避免因镜像损坏导致的安装中断。对于已停止支持的操作系统,如Windows 2000,其镜像获取与安装更具挑战性,但它在工业控制、专用终端及怀旧技术研究中仍有不可替代的价值。通过理解镜像命名规则、服务包等级(如SP4)及引导方式,结合虚拟机或老硬件平台,可以顺利完成部署。同时,驱动兼容性是老系统运行的关键瓶颈,需针对性解决网卡、显卡等外设驱动问题。本文从镜像下载、校验到安装配置,系统梳理了Windows

weixin_32050773的博客 339

QOS令牌桶算法

当数据流到达设备时首先会根据数据的大小从令牌桶中取出与数据大小相当的令牌数量用来传输数据。也就是说要使数据被传输必须保证令牌桶里有足够多的令牌,如果令牌数量不够,则数据会被丢弃或缓存。这就可以限制报文的流量只能小于等于令牌生成的速度,达到限制流量的目的2. 令牌桶术语令牌桶参数CBS(Committed Burst Size):承诺突发尺寸,表示C桶的容量,即C桶瞬间能够通过的承诺突发流量EBS(Extended burst size):超额突发尺寸,

zljszn的博客 2196

【Hypermesh】TetraMesh Panel 常用选项详解

结合Hypermesh 2020 帮助文档和自己的一点使用经验,整理了这个博客。

qgm1702的博客 3673

read文件一个字节实际会发生多大的磁盘IO?

先讲一个作者大约7年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性能肯定差。借由这个故事其实我发现了一个问题,虽然我们中的大部分人都是计算机科班出身,代码也写的很遛。但是在一些看似司空见惯的问题上,我们中的绝大多数人并没有真正理解,或者理解的不够透彻。 不管你用的是啥语言,C/PHP/GO、还是Java,相信大家都有过读取文件的经历。我们来思

zhangyanfei01的专栏 869

AI测试实战:用文心一言5分钟生成登录功能测试用例(附Excel模板)

本文详细介绍了如何利用AI工具(如文心一言)在5分钟内高效生成登录功能测试用例,并提供了可直接应用的Excel模板。通过对比传统手工编写与AI生成的效率差异,展示了AI在软件测试领域的巨大优势,包括减少重复劳动、避免边界条件遗漏和提升格式标准化。文章还包含实战技巧、高级应用方案和行业最佳实践,助力测试人员快速提升工作效率。

weixin_30379531的博客 410

Read文件一个字节实际会发生多大的磁盘IO?

以下内容转载自https://segmentfault.com/a/1190000037728927 闪念基因2020-11-05 11:45:45 作者:yanfei 出处:https://segmentfault.com/a/1190000037728927 先讲一个作者大约7年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性.

Shanks 294

云端办公文件存储与访问全攻略:选型、预算、实操一本通

随着远程办公、多设备协作成为常态,“文件云端存储、随时调用” 已成为提升办公效率的核心需求。本文从用户实际场景出发,系统拆解云端存储的选型逻辑、全场景费用预算,重点解答 “文件能否直接在线打开” 的核心疑问,并提供实操技巧与安全保障方案,覆盖个人、小团队(含兼职)、企业全维度需求,帮助不同规模用户快速搭建高效、低成本的云端办公体系。

hy行者勇哥的博客 1240

高数15种常见特殊曲线:星形线、心形线、摆线、对数螺线、双曲螺线、阿基米德螺线、伯努利双纽线、三叶玫瑰线、四叶玫瑰线、六叶玫瑰线、三次抛物线、半立方抛物线、箕舌线、蔓叶线、笛卡儿叶形线、概率曲线

4.1 对数螺线(等角螺线、生长螺线)三叶玫瑰线、四叶玫瑰线、六叶玫瑰线。​7.2 半立方抛物线(尼尔曲线)10.笛卡儿叶形线(茉莉花瓣曲线)常考选择题、填空题,大题也涉及。​4.2 双曲螺线(倒数螺线)11.阿基米德螺线(等速螺线)3.摆线(圆滚线、旋轮线)5.双纽线(伯努利双纽线)1.星形线(四尖瓣线)2.心形线(心脏线)..................

刘鑫磊 1万+

cfile read 最大读取限制_Read文件一个字节实际会发生多大的磁盘IO?

作者:yanfei出处:https://segmentfault.com/a/1190000037728927先讲一个作者大约7年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性能肯定差。借由这个故事其实我发现了一个问题,虽然我们中的...

weixin_39992072的博客 466

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

cfile read 最大读取限制_read文件一个字节实际会发生多大的磁盘IO?

先讲一个作者大约5-6年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就说,这个地方读文件啦,会导致磁盘IO的。借由这个故事其实我发现了一个问题,虽然我们中的大部分人都是计算机科班出身,代码也写的很遛。但是在一些看似司空见惯的问题上,我们中的绝大多数人并没有真正理解,或者理解的不够透彻。不管你用的是...

weixin_39843847的博客 797

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

一招修复内存不能read_read文件一个字节实际会发生多大的磁盘IO?

先讲一个作者大约5-6年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性能肯定差。借由这个故事其实我发现了一个问题,虽然我们中的大部分人都是计算机科班出身,代码也写的很遛。但是在一些看似司空见惯的问题上,我们中的绝大多数人并...

weixin_39958025的博客 245

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

linux+平均磁盘请求数量_Read文件一个字节实际会发生多大的磁盘IO?

作者:yanfei出处:https://segmentfault.com/a/1190000037728927先讲一个作者大约7年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性能肯定差。借由这个故事其实我发现了一个问题,虽然我们中的...

weixin_39711348的博客 230

cfile read 最大读取限制_read文件一个字节实际会发生多大的磁盘IO? - zhangyanfei01

先讲一个作者大约7年前我在某当时很火的一个应用分发创业公司的面试小插曲,该公司安排了一个刚工作1年多的一个同学来面我,聊到我们项目中的配置文件里写的一个开关,这位同学就跳出来说,你这个读文件啦,每个用户请求来了还得多一次的磁盘IO,性能肯定差。借由这个故事其实我发现了一个问题,虽然我们中的大部分人都是计算机科班出身,代码也写的很遛。但是在一些看似司空见惯的问题上,我们中的绝大多数人并没有真正理解,...

weixin_39609953的博客 322

java.io.FileInputStream类:文件字节输入流

java.io.FileInputStream类:文件字节输入流

听海边涛声 1193

Innodb Read IO 相关参数源代码解析

最近在阅读Innodb IO相关部分的源代码。在阅读之前一直有个疑问,show global status 中有两个指标innodb_data_reads 和innodb_data_read。两个计数器仅差一个字母,他们之间的含义到底有何差别呢?本文将通过解析这两个参数的含义,分析Innodb对于磁盘IO相关的一些知识

渔夫数据库笔记 1295
上一篇: 图解Linux网络包接收过程
下一篇: 25 张图,一万字,拆解 Linux 网络包发送过程
废言Pro
博客等级 码龄16年 1092粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值