当前位置: 首页 > Linux

LinuxStorageStackDiagram

时间:2023-04-06 12:05:29 Linux

在工作和学习中,没有什么比图表更好的了(虽然很多人都在嘲笑PPT),尤其是描述准确的图表。当你想画图来说明一个结构或一个过程时,一定要很好理解。在解释一张图的时候,也要对它有一个基本的了解。这真的不是那么简单,无论如何对我来说。关于LinuxStorage架构,有一张图描述的非常准确,《LinuxStorageStackDiagram》。这张照片总结得很好。Storage涉及的模块都进行了描述,让学习者能够清楚地了解这个复杂的系统。本文试图对图中的各个部分进行简要介绍,但不涉及具体实现。https://www.thomas-krenn.com/...图中用颜色来区分不同的组件。Azure:硬件存储设备。橙色:传输协议。蓝色:Linux系统中的设备文件。黄色:I/O调度策略。绿色:Linux系统的文件系统。Blue-green:BIO,LinuxStorage操作的基本数据结构。文件系统VFSVFS是Linux内核提供的虚拟文件系统层。VFS为用户层提供了一些标准的系统调用来操作文件系统,如open()、read()、write()等,使得用户态应用程序无需关心底层文件系统和储存媒介。同时,VFS也对底层文件系统进行了约束,提供了统一的抽象接口和运行方式。底层文件系统Linux支持的文件系统很多,大致可以分为以下几类。磁盘文件系统:基于物理存储设备的文件系统,用于管理设备的存储空间,如ext2、ext4、xfs等网络文件系统:用于访问网络中其他设备上的文件,如NFS、smbfs等网络文件系统的目标是网络设备,因此不会调用系统的块层。堆叠文件系统:一个文件系统叠加在其他文件系统之上。它本身不存储数据,而是扩展底层文件,如eCryptfs、Wrapfs等。伪文件系统:由于不管理真实的存储空间,所以称为伪文件系统。它组织了一些虚拟目录和文件,通过这些目录和文件可以访问系统或硬件数据。它不是用来存储数据的,而是用来访问数据封装层文件的,所以伪文件系统不能作为存储空间来操作。如proc、sysfs等。特殊文件系统:特殊文件系统也是一种伪文件系统。它的使用更像是一个磁盘文件系统,但读写的是内存而不是磁盘设备。如tmpfs、ramfs等。用户文件系统:也叫FUSE。它为开发人员提供了一种在不修改内核的情况下在用户空间实现文件系统的方法。这种方法更灵活,但效率较低。FUSE直接面向用户文件系统,不调用Block层。BlockLayerBlockLayer是Linux存储系统中的中间层,连接文件系统和块设备。它将上层文件系统的读写请求抽象为BIO,通过调度策略将BIO传递给设备。BlockLayer包含图中青色、黄色和中间BIOs传输过程。PagecacheLinux系统可以通过O_DIRECT标志来决定打开文件时是否使用Pagecache。使用O_DIRECT时,I/O读写会绕过缓存,直接访问块设备。否则需要通过Pagecache进行读写。Pagecache的主要行为如下。读取数据时,如果访问的页面在Pagecache中(命中),则直接返回该页面。读取数据时,如果访问的页面不在Pagecache中(缺失),就会出现pagefault异常。系统会创建一个缓存页面,并将访问的地址缓存到这个页面中。上层会再次读取,并发生缓存命中。写入数据时,如果缓存命中,则将数据写入缓存页。写入数据时,如果缓存缺失,会出现pagefault异常,系统会创建一个缓存页。上层再次写入,发生缓存命中。当页面缓存中的缓存页面被修改时,它被标记为脏。上层调用sync或pdflush进程将脏页写回磁盘。BIOBIO表示对Block设备的读写请求,在内核中用一个结构体来描述。//当前bvec中完成的数据大小,byte};结构生物{结构生物*bi_next;//请求队列structblock_device*bi_bdev;//指向块设备intbi_error;无符号整数bi_opf;//请求标记unsignedshortbi_flags;//状态,命令unsignedshortbi_ioprio;结构bvec_iterbi_iter;unsignedintbi_phys_segments;//合并物理地址后,BIO中的段数/**为了跟踪最大段大小,我们考虑了此bio中第一个和最后一个可合并段的*大小。*/unsignedintbi_seg_front_size;//第一个可合并段的大小unsignedintbi_seg_back_size;//最后一个可合并段的大小atomic_t__bi_remaining;bio_end_io_t*bi_end_io;//BIO函数结束时的回调,一般用于通知调用者BIO完成......无符号短bi_vcnt;//bio_vec的计数unsignedshortbi_max_vecs;//bvl_vecs的最大数量atomic_t__bi_cnt;//使用计数structbio_vec*bi_io_vec;//指向vec列表的指针structbio_set*bi_pool;......};BIO构建完成后,可以通过generic_make_request()创建一个传输Request,并将该Request添加到请求队列中。请求队列在内核中用结构体request_queue来描述,它包含了一个双向请求列表和相关的控制信息。请求列表中的每一项都是一个Request,Request由BIO组成,BIO可能包含不同的Segment。因为一个BIO只能是连续的磁盘块,而一个Request不一定是连续的磁盘块,所以一个Request可能包含一个或多个BIO。BIO中的磁盘块虽然是连续的,但在内存中不一定是连续的,所以BIO中可能包含几个Segment。Scheduler向请求队列中读写数据后,就是访问磁盘的过程,通过IO调度完成。BIO访问的指定磁盘扇区必须先进行寻址操作。寻址是将磁头定位到特定块上的某个位置的过程,速度比较慢。为了优化寻址操作,内核既不会简单地按顺序接收请求,也不会立即将请求提交到磁盘。相反,它将在提交之前执行称为合并和排序的预操作。这种预操作非常有效。大大提高了系统的整体性能。这就是IO调度需要做的事情。当前内核支持两种模式的IO调度器:单队列和多队列。图中单队列标识为“I/OScheduler”,多队列标识为blkmq。两者应该都是Scheduler,只是请求的组织方式不同。单队列通过合并和排序减少了磁盘寻道时间。合并是指将多个连续的请求合并为一个更大的IO请求,以充分发挥硬件性能。排序采用电梯调度,整个请求队列会按照扇区增长的方向有序排列。排列的目的不仅仅是为了缩短单个请求的寻道时间,更重要的优化是通过保持磁头直线运动来缩短所有请求的寻道时间。目前单队列使用的调度策略有:noop、deadline、cfq等。noop:IO调度器最简单的算法,将IO请求放入队列中依次执行这些IO请求,合并连续的IO请求因此。Deadline:保证IO请求能在一定时间内得到服务,避免某个请求饿死。CFQ:绝对公平算法,试图为所有竞争块设备使用权的进程分配一个请求队列和一个时间片。在调度器分配给进程的时间片内,进程可以向底层块设备发送读写请求。当进程的时间片耗尽时,进程的请求队列会被挂起,等待调度。较早的内核只有单队列。当时硬盘是主要的存储设备,硬盘的随机寻址性能很差。单队列即可满足传输要求。SSD发展起来,随机寻址性能很好,传输的瓶颈转移到了请求队列上。结合多核CPU,设计了多队列。Multi-queue为每个CPUcore或socket配置一个Softwarequeue,也解决了single-queue中多核锁竞争的问题。如果存储设备支持多个Hardwaredispatchqueues并行,传输性能将得到很大的提升。目前多队列支持的调度策略有:mq-deadline、bfq、kyber等块设备文件设备文件是linux系统访问硬件设备的接口,驱动将硬件设备抽象成设备文件,方便访问通过应用程序。加载设备驱动程序时,会在/dev/下创建一个设备文件描述符。如果是Block设备,会在/dev/block/下创建一个软链接,并根据设备号命名。图中,块设备分为以下几类。逻辑设备:图中“Devicesontopof'normal'blockdevices”,使用DeviceMapper映射物理块设备。通过这种映射机制,可以实现对存储资源的按需管理。包括LVM、DM、bcache等。SCSI设备:使用SCSI标准设备文件,包括sda(硬盘)、sr(光驱)等。其他块设备:每个块设备都有自己的传输协议。一类代表真实的硬件设备,比如mmc、nvme等。另一类代表虚拟块设备,如loop、zram等,传输协议图中橙色部分表示Block设备所依赖的技术实现,可能是硬件规范的软件实现,也可能是一个软件架构。图中SCSI和LIO分别圈出来了,因为这两部分比较复杂。SCSI包含了很多硬件规范,最常用的是通过libata访问HDD和SSD。LIO(Linux-IO)基于SCSI引擎,实现了SCSI系统模型(SAM)中描述的SCSITarget。LIO是在linux2.6.38之后引入内核的。其支持的SAN技术包括FibreChannel、FCoE、iSCSI、iSER、SRP、USB等,还可以为本机生成模拟的SCSI设备,为虚拟机提供基于virtio的SCSI设备。LIO使用户无需购买昂贵的专业设备,就可以使用相对便宜的Linux系统实现SCSI和SAN的各种功能。可以看出LIO的前端是一个Fabric模块(FibreChannel、FCoE、iSCSI等),用来访问模拟的SCSI设备。Fabric模块是实现SCSI命令的传输协议。例如iSCSI技术在TCP/IP中传输SCSI命令,vhost技术在virtio队列中传输SCSI命令。LIO的后端实现了访问磁盘数据的方法。FILEIO通过LinuxVFS访问数据,IBLOCK访问LinuxBlock设备,PSCSI直接访问SCSI设备,MemoryCopyRAMDISK用于访问模拟SCSI的ramdisks。硬件设备图中天蓝色的部分就是实际的硬件存储设备。其中virtio_pci、para-virtualizedSCSI、VMware的para-virtualizedscsi都是虚拟化硬件设备。