说到磁盘,这是数据持久化保存的一种保存媒介,也是计算机必不可少的一种硬件设备,而想要用到磁盘就必须提到文件系统。
文件系统
文件系统是构建在磁盘上的,用来管理文件的。为了方便管理,Linux为每个文件都分配了两个数据结构,索引节点(index node)和目录项(directory entry)他们主要用来记录文件的元信息和目录结构。
索引节点:又称为inode。用来记录文件的元数据,他和文件内容一样是会被持久化存储的。(存储到磁盘)
目录项:又称为dentry。用来记录文件的名字、索引节点指针以及与其他目录项的关联关系,目录项是由内核维护的一种内存数据结构。(内存缓存)
文件系统.png
每块磁盘在使用前都需要格式化,而格式化后就会被分成三个存储区,超级块,索引节点和数据块区。
超级块:存储整个文件系统的状态
索引节点区:用来存储索引节点
数据块区:存储数据。
VFS
Linux在用户进程空间与文件系统中间由引入了一个抽象层。也就是虚拟文件系统VFS。VFS定义了一组所有文件系统都支持的数据结构的标准接口。这样用户进程空间和内核只需要和VFS交互,而不需要关系各种文件系统底层的实现关系了。
如下图:
文件系统.png
值得注意的是,文件系统不仅仅有基于磁盘的文件系统,还有基于内存的虚拟文件系统,如/proc文件系统,再比如/sys 文件系统。/sys 主要向用户空间导出层次化的内核对象。
在Linux中,磁盘是作为一个块设备来管理的,并且支持随机读写,每块设备会被赋予两个设备号,分别是主设备号和次设备号。主设备号用在驱动程序中,用来区分设备,而次设备号用来给多个同类设备编号。
通用块层
Linux通过一个通用块层来管理各种不同的设备。它会将文件系统和应用程序发来的I/O请求排队,并通过重新排序、请求合并等方式来提高磁盘的读写效率。
对于I/O请求排序的过程,也就是I/O调度算法,通常Linux支持4种调度算法,分别是NONE,NOOP,CFQ以及DeadLine。
这里不做详细的介绍。只是简单提一下。
NONE 不做任何I/O调度,通常在虚拟机中,此时的磁盘I/O交给宿主机负责。
NOOP 先入先出队列,只做一些简单的请求合并。
CFQ 完全公平调度器。为每一个进程都维护一个I/O调度队列。并按事件片来均匀分布每一个进程的I/O请求。(最适合运行大量进程的系统)
DeadLine 分别为读、写请求创建了不同的I/O队列。多用在I/O压力比较重的场景,如日志归集,数据库服务器。
Linux的I/O
Linux的I/O栈就是由 文件系统,通用块和设备层组成了。
小结一下。
文件系统层:包括虚拟文件系统和其他各种文件系统的实现。它为上层的应用程序提供标准的访问接口。对下层通过通用块层来存储和管理磁盘数据。
通用块层: 管理块设备I/O队列和I/O调度器。会对文件系统传过来的I/O 请求进行排队&#