Linux 存储系统概览
Linux 存储栈概述
可以把Linux 存储子系统看成两个部分:
- 站在用户角度提供读写接口,数据以流的形式表现;
====中间是文件系统==== - 站在存储设备角度提供读写接口,数据以块的形式表现。

从系统调用接口开始(包含),以下都是内核空间,以上都是用户空间。
1)VFS
VFS 在具体文件系统之上建立一个抽象层,屏蔽各类文件系统的差异。
VFS 包含4类对象类型:
- super block:超级块对象,代表一个文件系统。
- inode:索引节点,代表设备上的一个物理文件,用户存储文件信息。
- dentry:目录项,目录路径上的各个组成部分,每个部分都是一个目录项对象。
- 文件:文件对象是一个被进程打开的文件,一个物理文件对应一个索引节点,但可能对应多个文件对象。
2-1)Page Cache
以物理页为单位对磁盘文件进行缓存,
free -h 中
- buffer:设备占用的缓存页,直接读写块设备,及文件系统元数据,如superblock 等
- cache:普通文件所占用的缓存页
2-2)Direct IO
适用于自缓存应用,一般与AIO 一起使用。
块设备文件: 在使用Direct IO时,通常搭配Libaio使用,避免同步IO阻塞程序。而往往Direct IO + Libaio应用于裸设备的场景。
libaio 的调用栈:write()--->sys_write()--->vfs_write()--->通用块层--->IO调度层--->块设备驱动层--->块设备
3)Mapping Layer(映射层)
在文件访问和设备访问之间做映射。由多个文件系统(XFS等,打开文件系统的文件)以及块设备文件(直接打开裸设备文件)组成,主要完成两个工作:
- 内核确定该文件所在文件系统或者块设备的块大小,并根据文件大小计算所请求数据的长度以及所在的逻辑块号。
- 根据逻辑块号确定所请求数据的物理块号,也即在在磁盘上的真正位置。
4)Block Layer(通用块层)
维持一个IO 请求在上层文件系统与底层物理设备之间的关系。
bio 和request 是块层最核心的两个概念:
- 每个bio 对应块设备中一块连续的位置:其中bio 描述了其在存储设备中真实操作的位置和Page cache 中的映射位置。
- request 用来描述一个IO 请求,一个request 可能包含多个bio。
IO 调度子层将bio 和设备驱动的request 关联。
Linux IO 调度算法
- 电梯算法:一直上然后一直下。
- deadline:基于电梯算法,在超时后会掉在方向。
- CFQ:完全公平队列,基于时间片和优先级的队列调度。
5)块设备驱动层
每一类设备都有其驱动程序,负责设备的读写。
通常块设备的驱动程序都已经集成在了kernel里面,也即就算我们直接调用块设备驱动层的代码还是要经过内核。
spdk实现了用户态、异步、无锁、轮询方式NVME 驱动程序。

浙公网安备 33010602011771号