文件系统是对存储设备上的文件,进行组织管理的一种机制,而linux再文件实现上,又抽象了一层虚拟文件系统VFS,它定义了一组,所有文件系统都支持的数据结构和标准接口
对于应用程序来说,只需要跟VFS提供的统一接口交互,而不需要关系文件系统的具体实现,对于文件系统来说,只需要按照VFS的标准,就可以无缝支持各种应用程序.
VFS内部又通过目录项\索引节点\逻辑块以及超级快等数据结构来管理文件.
目录项,记录了文件的名字,已经文件与其他目录项之间的目录关系
逻辑块:是由连续磁盘扇区构成的最小读写单元,用来存储文件数据
索引节点:记录了文件的元数据(元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能)
超级块:用来记录文件系统整体的状态,如索引节点和逻辑块的使用情况等
其中,目录项是一个内存缓存,而逻辑块,索引节点,超级块都是存储再磁盘上的持久化数据
磁盘
磁盘是可以持久化存储的设备,根据存储的介质不同,常见的磁盘可以分为,机械磁盘和固态磁盘
机械磁盘:也称为硬盘驱动器,缩写HDD,主要有盘片和读写磁头组成,数据就存储再盘片的环状磁道内,再读写数据前,需要移动读写磁头,定位到数据所在的磁道,然后才能访问,显然,如果I/O请求刚好连续,那就不需要磁道寻址,自然可以获得最佳性能,这就是连续I/O的工作原理,与之相对的就是随机I/O,他需要不停的移动磁头,来定位数据的位置,所以读写速度会比较慢
固态磁盘:缩写SSD,由固态电子元器件组成,固态磁盘不需要磁道寻址,所以不管是连续I/O,还是随机I/O的性能,都要比机械磁盘要好的多,但不管怎么说,相同磁盘的随机I/O都要比连续I/O慢很多,虽然固态磁盘的随机读写要比机械磁盘的性能好很多,但同样存在"先擦除再写入"的限制,随机读写会出现大量的垃圾回收,所以相对应的,随机I/O的性能比连续I/O的性能差很多,连续I/O可以通过预读的方式,来减少I/O的请求次数,这也是其性能优异的原因,很多性能优化方案,也可以从这个角度触发来优化I/O性能
此外,机械磁盘和固态磁盘分别还有一个最小的读写单位
机械磁盘的最小读写单位是扇区,一半大小为512字节
固态磁盘的最小读写单位是页,通常大小为4KB,8KB等
如果每次都读取512字节这么小的单位的话,效率很低,所以文件系统会把连续的扇区或页,组成逻辑块,然后以逻辑块来作为最小单元管理数据,常见的逻辑块大小是4KB,也就是说,连续8个扇区,或者单独一个页,都可以组成一个逻辑块
当磁盘接入服务器后,根据他们不同的使用方式,又可以把他们划分为多种不同的架构
最简单的就是作为独立磁盘来使用,这些磁盘往往会更具需要,划分为不同的逻辑区,每个分区再用数字编号,比如/dev/sda1,/dev/sda2
另一种比较常用的架构,是把多个磁盘组合成一个逻辑磁盘,构成冗余独立磁盘整列,也就是RAID,从而提高数据访问的性能,并增强数据存储的可靠性,更具容量\性能\和可靠性的不同,RAID一般可以分为多个级别,如RAID0,RAID1....等
RAID0有最优的读写性能,但不提供数据冗余的功能
而其他级别的RAID,再提供数据冗余的基础上,对读写性能也有一定程度的优化
最后一种架构,是把这些磁盘组合成一个网络存储集群,再通过NFS,SMB,iSCSI等网络存储协议,暴露给服务器使用
再linux种,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写,每个块设备都会被赋予两个设备号,分别为主,次设备号,主设备号用于设备驱动中,用来区分设备类型;而次设备号是用来给多个同类设备编号
通用块层
处在文件系统和磁盘驱动中间的一个块设备抽象层,它主要有两个功能
1:跟虚拟文件系统功能类似,向上,为文件系统和应用程序,提供访问块设备的标准接口;向下,把各种异构的磁盘设备抽象为统一的块设备,并提供统一框架来管理这些设备的驱动程序
2:通用块层还给文件系统和应用程序发来I/O请求排队,并通过重新排序,请求合并等方式,提高磁盘的读写效率
其中I/O请求排序的过程,也就是我们熟悉的i/o调度,事实上,linux内核支持这种I/O调度算法,分别为NONE,NOOP,CFQ以及DeadLine
NONE:确切的说不能算是I/O调度算法,因为它不适用任何I/O调度器,对文件系统和应用程序的I/O不做任何处理,常用在虚拟环境中(此时I/O调度完全由物理机负责)
NOOP:最简单的调度算法,它实际上是一个先入先出的队列,只做一些基本的请求合并,常用于SSD
CFQ:也被称为完全公平调度器,是现在很多发行版的默认I/O调度器,它为每个进程维护了一个I/O调度队列,并按照时间片来均匀分布每个进程的I/O请求,类似与进程CPU调度,CFQ还支持进程I/O的优先级调度,所以它使用于运行大量经常的系统,像桌面应用,多媒体应用等
DeadLine:分别为读\写请求创建不同的I/O队列,可以提高机械磁盘的吞吐量,并确保达到最终期限(deadline)的请求被优先处理,Deadline算法多用I/O较重的场景,例如数据库等
I/O栈
I/O栈由上到下可以分为3个层次,分别是文件系统,通用块层和设备层
文件系统层:包括虚拟文件系统和其他文件系统的具体实现,它为上层的应用程序,提供标准的文件访问接口,对下会通过通用块层,来存储和管理磁盘数据
通用块层:包括设备I/O队列和I/O调度器,它会对文件系统的I/O请求进行排队,再通过重新排序和请求合并,然后再发送给下一层的设备层
设备层:包括存储设备和相应的驱动程序,负责最终物理设备的 I/O 操作
存储系统的I/O,通常是整个系统中最慢的一环,所以,Linux通过多种缓存机制来优化I/O效率
为了优化文件访问的性能,会使用页缓存\索引节点缓存\目录项缓存等多种缓存机制,以减少对下层块设备的直接调用,同样,为了优化块设备的访问效率,会使用缓冲区,来缓存块设备的数据