IO 技术栈
提供了软件与其它数据存储介质交换数据的能力
Linux 系统 I/O 栈主要包括磁盘和文件系统:
1. 磁盘:为系统数据提供持久化存储,在 linux 系统中磁盘是作为一个块设备来管理的,以块为单位读写数据,通常包括本地磁盘设备和网络存储
2. 文件系统:提供管理系统文件的树状结构,在 linux 系统中,一切皆文件,普通的文件、目录、块设备、套接字以及管道都是通过统一的文件系统管理,文件系统为每个文件都分配一个索引节点及一个目录项数据结构,用来记录文件的元信息及目录结构:
- 索引节点:inode 用来记录文件的大小,修改日期,访问权限、数据位置等元信息,inode 跟文件一一对应,inode 信息也要持久化存储到磁盘
- 目录项结构:dentry 用来记录文件的名字、索引节点指针以及与其他目录项的关联关系,目录项存储在内存中
换句话说,索引节点是每个文件的唯一标志,而目录项维护的正是文件系统的树状结构。目录项和索引节点的关系是多对一,你可以简单理解为,一个文件可以有多个别名。
举个例子,通过硬链接为文件创建的别名,就会对应不同的目录项,不过这些目录项本质上还是链接同一个文件,所以,它们的索引节点相同。
索引节点和目录项纪录了文件的元数据,以及文件间的目录关系,那么具体来说,文件数据到底是怎么存储的呢?是不是直接写到磁盘中就好了呢?
实际上,磁盘读写的最小单位是扇区,然而扇区只有 512B 大小,如果每次都读写这么小的单位,效率一定很低。所以,文件系统又把连续的扇区组成了逻辑块,然后每次都以逻辑块为最小单元,来管理数据。常见的逻辑块大小为 4KB,也就是由连续的 8 个扇区组成。
第一,目录项本身就是一个内存缓存,而索引节点则是存储在磁盘中的数据。在前面的 Buffer 和 Cache 原理中,我曾经提到过,为了协调慢速磁盘与快速 CPU 的性能差异,文件内容会缓存到页缓存 Cache 中。
那么,这些索引节点自然也会缓存到内存中,加速文件的访问。
第二,磁盘在执行文件系统格式化时,会被分成三个存储区域,超级块、索引节点区和数据块区。其中,
- 超级块,存储整个文件系统的状态。
- 索引节点区,用来存储索引节点。
- 数据块区,则用来存储文件数据。
文件系统,本身是对存储设备上的文件,进行组织管理的机制。组织方式不同,就会形成不同的文件系统。
换句话说,索引节点是每个文件的唯一标志,而目录项维护的正是文件系统的树状结构。目录项和索引节点的关系是多对一,你可以简单理解为,一个文件可以有多个别名。
举个例子,通过硬链接为文件创建的别名,就会对应不同的目录项,不过这些目录项本质上还是链接同一个文件,所以,它们的索引节点相同。
虚拟文件系统级缓存
虚拟文件系统:VFS 给不同类型的文件系统提供了通用的接口,用户程序和内核其他子系统不需要了解各种文件系统的实现细节,通过 VFS 提供的接口就可以实现对文件系统的调用,VFS 是处于系统调用和文件系统中间的一个抽象层,EXT3、EXT4、NFS 等文件系统需要挂载到 VFS 目录树中的某个子目录下面才能被使用,比如 LINUX 系统的根目录/
这些文件系统可以分为三类。
- 第一类是基于磁盘的文件系统,也就是把数据直接存储在计算机本地挂载的磁盘中。常见的 Ext4、XFS、OverlayFS 等,都是这类文件系统。
- 第二类是基于内存的文件系统,也就是我们常说的虚拟文件系统。这类文件系统,不需要任何磁盘分配存储空间,但会占用内存。我们经常用到的 /proc 文件系统,其实就是一种最常见的虚拟文件系统。此外,/sys 文件系统也属于这一类,主要向用户空间导出层次化的内核对象。
- 第三类是网络文件系统,也就是用来访问其他计算机数据的文件系统,比如 NFS、SMB、iSCSI 等。
这些文件系统,要先挂载到 VFS 目录树中的某个子目录(称为挂载点),然后才能访问其中的文件。拿第一类,也就是基于磁盘的文件系统为例,在安装系统时,要先挂载一个根目录(/),在根目录下再把其他文件系统(比如其他的磁盘分区、/proc 文件系统、/sys 文件系统、NFS 等)挂载进来。
缓存:为了协调快速 CPU 及慢速磁盘之间的性能差异,LINUX 文件系统通过各种缓存实现文件的快速访问,主要包括:
- 页缓存:缓存了虚拟内存页面,其中包括了文件系统的页面,提升了文件和目录的性能,当系统系统内存不足时,页缓存是可以回收的,可通过如下命令:
grep "Cached" /proc/meminfo
查看系统页缓存大小 - 目录项缓存:dentry 记录了从目录项到 VFS inode 的映射关系,提高了路径名查找的性能, 可通过如下命令:
grep "dentry" /proc/slabinfo
查看系统目录项缓存大小 - 索引节点缓存: inode_cache 缓存的对象是 inode,包括文件访问权限、更新时间戳、文件大小等信息,可通过如下命令:grep "inode_cache" /proc/slabinfo 查看索引节点缓存大小
文件缓存是这么计算的
/proc/meminfo 中
11 Active(file): 728232 kB
12 Inactive(file): 400104 kB
这两个值得总和
磁盘 IO
在 linux 系统中磁盘是作为一个块设备来管理的,以块为单位读写数据,为了减少不同的块设备差异带来的影响,类似虚拟文件系统 VFS,linux 通过一个统一的通用块层来管理各种块设备,主要功能如下:
- 为文件系统和应用程序,提供访问块设备的标准接口,将各种磁盘设备抽象为统一的块设备来管理
- 对 I/O 请求进行调度,通过重新排序,请求合并等措施优化磁盘读写效率
I/O 调度器对 I/O 请求进行排序,具体由采用的调度策略决定,主要策略如下
- None:不做任何调度,常用于虚拟机,磁盘 I/O 调度取决了宿主物理机策略
- Noop:一个先入先出的队列,只做一些基本的请求合并,适用于 SSD 磁盘
- Deadline:为每个 I/O 请求延时设定截止时间,将要达到截止时间的请求被优先处理,共使用三个队列:读 FIFO、写 FIFO 和排序队列,通常适用于 I/O 求情大量的业务,比如数据库
- Cfq:完全公平队列调度把 I/O 时间片分配给进程,确保磁盘资源的公平使用,通常作为默认选项,可通过 ionice 命令对用户进程设定优先级和类别
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: iops dump 使用手册
下一篇: IO 的类型
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论