1.如何工作
磁盘为操作系统提供了基本的持久化存储
文件系统则在磁盘的基础上,提供了一个用来管理文件的树状结构
索引节点,简称为 inode,用来记录文件的元数据,比如 inode 编号、文件大小、访问
权限、修改日期、数据的位置等。索引节点和文件一一对应,它跟文件内容一样,都会
被持久化存储到磁盘中。所以记住,索引节点同样占用磁盘空间。
目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的关联
关系。多个关联的目录项,就构成了文件系统的目录结构。不过,不同于索引节点,目
录项是由内核维护的一个内存数据结构,所以通常也被叫做目录项缓存。
索引节点,简称为 inode,用来记录文件的元数据,比如 inode 编号、文件大小、访问权限、修改日期、数据的位置等。索引节点和文件一一对应,它跟文件内容一样,都会被持久化存储到磁盘中。所以记住,索引节点同样占用磁盘空间。
目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构。不过,不同于索引节点,目录项是由内核维护的一个内存数据结构,所以通常也被叫做目录项缓存。
虚拟文件系统
文件系统I/O
第一种,根据是否利用标准库缓存,可以把文件 I/O 分为缓冲 I/O 与非缓冲 I/O。
缓冲 I/O,是指利用标准库缓存来加速文件的访问,而标准库内部再通过系统调度访问文件。
非缓冲 I/O,是指直接通过系统调用来访问文件,不再经过标准库缓存。
第二,根据是否利用操作系统的页缓存,可以把文件 I/O 分为直接 I/O 与非直接 I/O。
直接 I/O,是指跳过操作系统的页缓存,直接跟文件系统交互来访问文件。
非直接 I/O 正好相反,文件读写时,先要经过系统的页缓存,然后再由内核或额外的系统调用,真正写入磁盘。
第三,根据应用程序是否阻塞自身运行,可以把文件 I/O 分为阻塞 I/O 和非阻塞 I/O:
所谓阻塞 I/O,是指应用程序执行 I/O 操作后,如果没有获得响应,就会阻塞当前线程,自然就不能执行其他任务。
所谓非阻塞 I/O,是指应用程序执行 I/O 操作后,不会阻塞当前的线程,可以继续执行其他的任务,随后再通过轮询或者事件通知的形式,获取调用的结果。
第四,根据是否等待响应结果,可以把文件 I/O 分为同步和异步 I/O:
所谓同步 I/O,是指应用程序执行 I/O 操作后,要一直等到整个 I/O 完成后,才能获得I/O 响应。
所谓异步 I/O,是指应用程序执行 I/O 操作后,不用等待完成和完成后的响应,而是继续执行就可以。等到这次 I/O 完成后,响应会用事件通知的方式,告诉应用程序。
2.Linux 磁盘I/O是怎么工作的(上)
磁盘:
- 机械磁盘
- 需要寻址,移动磁头
- 直接Io快,随机IO慢,因为随机IO需要重新寻址
- 最小单位是扇区,一般大小为512字节
- 固态磁盘
- 不需要寻址
- 但是随机IO还是比直接IO慢,因为随机IO需要先擦除再写入
- 最小单位是页,一般为4KB、8KB等
扇区是磁盘读写的最小单位,一个扇区是512字节,比较小,所以将连续的扇区组成一个逻辑块,每次都以逻辑块为最小单位,管理数据。
Linux-storage-stack-diagram_v4.0.pdf
3.Linux 磁盘I/O是怎么工作的(下)
磁盘性能指标
1.使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
2.饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
3.IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
4.吞吐量,是指每秒的 I/O 请求大小。
5.响应时间,是指 I/O 请求从发出到收到响应的间隔时间。
4.案例篇:如何找出狂打日志的“内鬼”?
文件系统,是对存储设备上的文件进行组织管理的一种机制。为了支持各类不同的文件系统,Linux 在各种文件系统上,抽象了一层虚拟文件系统 VFS。它定义了一组所有文件系统都支持的数据结构和标准接口。这样,应用程序和内核中的其他子系统,就只需要跟 VFS 提供的统一接口进行交互。在文件系统的下层,为了支持各种不同类型的存储设备,Linux 又在各种存储设备的基础上,抽象了一个通用块层。
通用块层,为文件系统和应用程序提供了访问块设备的标准接口;同时,为各种块设备的驱动程序提供了统一的框架。此外,通用块层还会对文件系统和应用程序发送过来的 I/O请求进行排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。通用块层的下一层,自然就是设备层了,包括各种块设备的驱动程序以及物理存储设备。
文件系统、通用块层以及设备层,就构成了 Linux 的存储 I/O 栈。存储系统的 I/O ,通常是整个系统中最慢的一环。所以,Linux 采用多种缓存机制,来优化 I/O 的效率,比方说,
1.为了优化文件访问的性能,采用页缓存、索引节点缓存、目录项缓存等多种缓存机制,减少对下层块设备的直接调用。
2.同样的,为了优化块设备的访问效率,使用缓冲区来缓存块设备的数据。不过,在碰到文件系统和磁盘的 I/O 问题时,具体应该怎么定位和分析呢?今天,我就以一个最常见的应用程序记录大量日志的案例,带你来分析这种情况。
5.如何迅速分析出系统I/O的瓶颈在哪里
性能指标
文件系统 I/O 性能指标
首先,最容易想到的是存储空间的使用情况,包括容量、使用量以及剩余空间等。我们通常也称这些为磁盘空间的使用量,因为文件系统的数据最终还是存储在磁盘上。不过要注意,这些只是文件系统向外展示的空间使用,而非在磁盘空间的真实用量,因为文件系统的元数据也会占用磁盘空间。而且,如果你配置了 RAID,从文件系统看到的使用量跟实际磁盘的占用空间,也会因为RAID 级别的不同而不一样。比方说,配置 RAID10 后,你从文件系统最多也只能看到所有磁盘容量的一半。除了数据本身的存储空间,还有一个容易忽略的是索引节点的使用情况,它也包括容量、使用量以及剩余量等三个指标。如果文件系统中存储过多的小文件,就可能碰到索引节点容量已满的问题。其次,你应该想到的是前面多次提到过的缓存使用情况,包括页缓存、目录项缓存、索引节点缓存以及各个具体文件系统(如 ext4、XFS 等)的缓存。这些缓存会使用速度更快的内存,用来临时存储文件数据或者文件系统的元数据,从而可以减少访问慢速磁盘的次数。除了以上这两点,文件 I/O 也是很重要的性能指标,包括 IOPS(包括 r/s 和 w/s)、响应时间(延迟)以及吞吐量(B/s)等。在考察这类指标时,通常还要考虑实际文件的读写情况。比如,结合文件大小、文件数量、I/O 类型等,综合分析文件 I/O 的性能。诚然,这些性能指标非常重要,但不幸的是,Linux 文件系统并没提供,直接查看这些指标的方法。我们只能通过系统调用、动态跟踪或者基准测试等方法,间接进行观察、评估。不过,实际上,这些指标在我们考察磁盘性能时更容易见到,因为 Linux 为磁盘性能提供了更详细的数据。
磁盘 I/O 性能指标
接下来,我们就来具体看看,哪些性能指标可以衡量磁盘 I/O 的性能。
在磁盘 I/O 原理的文章中,我曾提到过四个核心的磁盘 I/O 指标。
使用率,是指磁盘忙处理 I/O 请求的百分比。过高的使用率(比如超过 60%)通常意味
着磁盘 I/O 存在性能瓶颈。
IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
吞吐量,是指每秒的 I/O 请求大小。
响应时间,是指从发出 I/O 请求到收到响应的间隔时间。
除了这些指标外,在前面 Cache 和 Buffer 原理的文章中,我曾多次提到,缓冲区
(Buffer)也是要重点掌握的指标,它经常出现在内存和磁盘问题的分析中。
性能工具
第一个维度,从文件系统和磁盘 I/O 的性能指标出发。换句话说,当你想查看某个性能指
标时,要清楚知道,哪些工具可以做到。
第二个维度,从工具出发。也就是当你已经安装了某个工具后,要知道这个工具能提供哪
些指标。
如何迅速分析 I/O 的性能瓶颈
- 先用 iostat 发现磁盘 I/O 性能瓶颈;
- 再借助 pidstat ,定位出导致瓶颈的进程;
- 随后分析进程的 I/O 行为;
- 最后,结合应用程序的原理,分析这些 I/O 的来源。
参考
- linux性能优化实践-倪鹏飞