大话存储系列7——文件系统和IO处理流程

简介: 1、文件系统 在早期的计算机系统中,每个程序都必须自己管理磁盘,在磁盘中放自己的数据,程序需要直接和磁盘控制器打交道。有多少个程序要利用磁盘,就有多少个磁盘交互启动接口。

1、文件系统

在早期的计算机系统中,每个程序都必须自己管理磁盘,在磁盘中放自己的数据,程序需要直接和磁盘控制器打交道。有多少个程序要利用磁盘,就有多少个磁盘交互启动接口。

在没有文件系统的计算机上,如果一个程序要向磁盘上存储一些自己的数据,那么这个程序只能自己调用磁盘控制器启动(无VM的情况下),或者调用VM提供的接口,对磁盘写数据。而写完数据后,很有可能被其他程序的数据覆盖掉。引入文件系统后,各个程序之间都通过文件系统接口访问磁盘,所有被写入的数据都称为一个文件,有着自己的名字,是一个实体。而且其他程序写入的数据,不会将其他人的文件数据覆盖掉,因为文件系统会保障这一点。

文件系统是操作系统用于明确磁盘或分区上的文件的方法和数据结构即在磁盘上组织文件的方法。也指用于存储文件的磁盘或分区,或文件系统种类。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:与文件管理有关软件、被管理文件以及实施文件管理所需数据结构。从系统角度来看,文件系统是对文件存储器空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。

更多文件系统知识请参考博客:http://www.ibm.com/developerworks/cn/linux/l-linux-filesystem/

2、IO处理流程

IO Manager是操作系统内核的一个模块,专门用来管理IO,并协调文件系统、卷、磁盘驱动程序各个模块之间的运作。整个流程解释如下:

**某个时刻,某个应用程序调用文件系统接口,准备写入某文件从某个字节开始的若干字节。

**IO Manger 最终将这个请求发送给文件系统模块。

**文件系统将某个文件对应的逻辑偏移映射成卷的LBA地址偏移。

**文件系统向IO Manager 请求调用卷管理软件模块的接口。

卷管理软件将卷对应的LBA地址偏移翻译映射成实际物理磁盘对应的LBA 地址偏移,并请求调用磁盘控制器驱动程序。

**IO Manger 想磁盘控制器驱动程序请求将对应LBA地址段的数据从内存中写入某块物理磁盘。


Windows操作系统中(以Windows2000/XP为例),一个典型的I/O请求要通过一系列复杂的操作实现:

讨论Windows 系统的I/O操作的流程之前,不得不提及Windows的I/O系统结构。简单说来,从虚拟机的角度来说,Windows的I/O系统是一个层层封装的虚拟机。Windows在系统核心中,对设备进行了数层封装:直接构建在设备上的是硬件抽象层(HAL),在此之上的是设备驱动程序,然后是I/O系统(I/O管理器、电源管理、WDM、WMI例程等);同时还有许多在用户态运行的系统服务如WMI服务,方便应用程序管理I/O设备。正因为有这种复杂的层次结构,统一管理、兼容成百上千不同种类的系统设备才成为可能。各个抽象层次把硬件结构上的多样性屏蔽掉,使用户能够按照一个统一的方式进行I/O操作。由于这里主要讨论I/O处理流程,I/O系统的结构不做细致阐述。

以下以打开一个文件对象的过程为例,说明Windows I/O请求的处理流程:

打开文件对象(File Object)

  1. 子系统调用一个I/O系统服务,打开一个有名字的文件。
  2. I/O管理器(I/O Manager)调用对象管理器(Object Manager)查找这个文件并帮助它找到所有相关的符号链接。同时也调用安全引用监视器(Security Reference Monitor)检查这个子系统是否有打开这个文件对象的权限。
  3. 如果这个文件所在的卷还没有装入,那么I/O管理器暂时挂起这个请求,调用其他文件系统,直到装有这个文件的卷装入,然后I/O管理器恢复刚才挂起的请求。
  4. I/O管理器为文件打开请求的IRP初始化分配内存。对于驱动程序而言,文件打开请求等价于一个"create"请求。
  5. I/O管理器调用文件系统驱动程序,向它发送IRP。文件系统驱动程序访问它在IRP中的I/O堆栈单元(I/O stack location)以决定要进行什么操作,检查参数,决定是否需要通过cache访问文件。如果不需要,在IRP中建立更低一级驱动程序的I/O堆栈单元。
  6. 各级驱动程序处理IRP完成这个I/O操作请求,会调用I/O管理器和其他系统组件提供的核心态支持例程。
  7. 驱动程序在IRP中设置I/O状态块(指明操作是否成功或错误代码),并将IRP返回到I/O Manager。
  8. I/O管理器从IRP中获得I/O状态,通过被保护的子系统将状态信息返回到原始调用者处。
  9. I/O管理器释放已经完成任务的IRP。
  10. 如果操作成功,I/O管理器返回这个文件对象的句柄到子系统;否则返回相应的失败状态。

如果打开成功,子系统就可以通过句柄来对这个设备进行各种I/O操作。其他操作的工作流程与此类似。I/O管理器会根据不同的请求类型产生相应的IRP发送到相应的驱动程序中执行特定的操作。

以上处理流程虽然复杂,但去掉一些细节后,总脉络是清晰的:I/O请求先陷入到系统核心,从上依层次向下将指令传到设备,执行结果依次向上返回到调用进程,切换回用户态。

整个流程中,有几个重要的数据结构:

文件对象(File Object):文件对象是一种逻辑上的对象,它并不仅仅可以代表文件,事实上它可以代表许许多多不同的物理设备(键盘、打印机、屏幕……当然也可以代表文件)。它事实上提供的是一种基于内存共享的物理资源表示法。每个文件对象对应一个句柄,用户程序通过这个句柄实现各种I/O操作。具体说,通过写入/查询特定的内存区段的,即可实现和物理设备的通讯。Windows所有的I/O操作都通过这种虚拟的文件对象进行,它隐藏了I/O操作目标的实现细节,为各种不同的物理设备提供了一个统一的操作接口。

驱动程序对象(Driver Object)和设备对象(DeviceObject):驱动程序对象代表系统中一个独立的驱动程序,并且为I/O记录每个驱动程序的调度例程的地址(入口点);设备对象代表系统中的一个物理、逻辑或虚拟的设备(注意,并不一定是物理设备!)并描述其特征。

总体上看,可以认为驱动程序对象是在功能上的抽象(对应某个“操作”),设备对象是结构上的抽象(对应某个“设备”)。完成某个操作通常需要用到多个设备,所以驱动程序对象通常有多个与它相关的设备对象。

尽管驱动程序对象和设备对象所封装的功能和设备是各种各样的,但它们都有统一的模型和接口,所以I/O管理器可以统一对它们进行管理和调用,而不用在意其具体内部结构的不同。

I/O请求包(IRP)是I/O系统用来存储处理I/O请求所需信息(例如请求的类型和大小、是同步请求还是异步请求、指向缓冲区的指针和进展状态信息等)的地方。由前面的例子可以看到,在整个系统内核中的I/O处理流程中,所有的调用/返回/控制信息都是由IRP传递的。它在I/O请求开始时由I/O管理器创建,在I/O处理完成后被释放,它是I/O处理中负责信息传递的最主要数据结构,即所谓以IRP驱动的I/O处理机制。

以上四种数据结构完整的抽象出了一个I/O请求的方方面面,它们在逻辑上把形形色色的I/O操作都统一起来,使用户可以不理会具体实现的细节,用几乎同样的方式实现各种I/O操作。

在整个I/O系统中,I/O管理器无疑是非常重要的,具有核心地位。顾名思义,它负责所有I/O请求的调度和管理工作。根据请求的不同内容,选择相应的驱动程序对象,设备对象,并生成、发送、释放各种不同的IRP。整个I/O处理流程是在它的指挥下完成的。

另外,完成I/O操作还需要有许多系统中其他服务的支持,总体上被称为驱动程序支持例程。

大体流程概括如下图(课本P317页图7.12所描述的也是这个结构):


事实上由于I/O操作种类繁多,它们有不同的需求和特点,所以Windows提供了不同的I/O操作选项。主要的I/O操作类型有:同步I/O和异步I/O,快速I/O(注意:快速I/O模式比较特殊,不使用IRP),映射文件I/O和文件高速缓存,分散/集中I/O。各种I/O操作类型的内部处理步骤是很不一样的。同时,单层和多层的驱动程序也有不同的执行策略。这些涉及到过多的细节和Windows驱动程序模型(WDM),在此不更多的展开讨论。

虽然具体到每一个I/O请求处理策略会各有不同,但总的来说,涉及到的操作对象和数据结构就是前面提到的那些。而且总的处理脉络仍然是:I/O请求先陷入到系统核心,从上依层次向下将指令传到设备,执行结果依次向上返回到调用进程,切换回用户态。

 

参考资料:

l  《操作系统教程》

l  《MSDN Library》 DDK部分


相关文章
|
4月前
|
存储 Linux Shell
Linux基础IO【深入理解文件系统】
Linux基础IO【深入理解文件系统】
56 1
|
6月前
|
存储 Linux 编译器
Linux之基础IO文件系统讲解(下)
因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访问的。所以C库当中的FILE结构体内部,必定封装了fd
Linux之基础IO文件系统讲解(下)
|
6月前
|
存储 Linux Shell
Linux之基础IO文件系统讲解(中)
文件描述符的分配规则 看下面代码
|
6月前
|
存储 Unix Linux
Linux之基础IO文件系统讲解(上)
在C语言中,读文件和写文件是常见的操作,用于从磁盘读取数据到内存或将数据从内存写入磁盘文件中。这些操作需要使用标准库中的文件I/O函数。下面我将详细解释如何在C语言中进行读文件和写文件操作,并举例说明。
|
8月前
|
存储 算法 大数据
倚天性能优化--基于倚天优化后的zstd在大数据场景应用:降低存储成本+提升重IO场景性能
倚天性能优化--基于倚天优化后的zstd在大数据场景应用:降低存储成本+提升重IO场景性能
|
9月前
|
存储 缓存 Linux
【Linux】基础IO——文件系统|软硬链接|动静态库
磁盘的结构、文件系统、软硬链接和动静态库
|
9月前
|
存储 安全 IDE
Linux基础IO【理解文件系统】
Linux理解文件系统,包括物理磁盘的介绍,文件系统的深入理解等相关知识,详细讲解,干货满满!
125 0
Linux基础IO【理解文件系统】
|
10月前
|
存储 人工智能 Cloud Native
高性能存储SIG月度动态:io_uring支持nvme直通,DSMS完成开发测试
Cloud Kernel SIG 月度动态送达,一键了解 5 月各项目进展。
|
10月前
|
存储 缓存 算法
【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(下)
【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(下)
139 1
|
10月前
|
存储 Linux 编译器
【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(上)
【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(上)
148 0