缓存管理器是什么

缓存管理器

Windows 的缓存管理器是一组内核模式的函数和系统例程,为所有的Windows文件系统驱动程序提供了系统缓存的能力。

 

Windows 缓存管理器按照虚拟地址为基础来缓存数据,它被赋予系统虚拟地址空间中的一个区域来进行管理。缓存管理器将每个地址空间区域分成256KB 的槽,称为视图:

 

系统中每个256KB 的槽都是通过一个VACB 来描述的;每个被单独打开的、被缓存的文件都有一个私有的缓存表,其中包含了用于控制预读的信息;

每个被缓存的文件都有一个共享的缓存表结构,它指向系统缓存中包含有该文件映射视图的那些槽

 

VACB 数组的地址存储在变量CcVacbs 中。

VACB中的第一个域是数据在系统缓存中的虚拟地址。 第二个域是一个指针,指向共享的缓存表结构,它标识了哪个文件被缓存了。第三个域标识了该视图在文件内部的偏移(总是以256KB粒度为基础)。最后,VACB包含了该视图的引用数,也就是说,有多少活动的读或写操作正在访问该视图。非零时,此VACB是活动的(active)。对于文件系统元数据的访问,活动计数代表了有多少个文件系统驱动程序使该视图中的页面锁定在内存中。

 

 

针对每个文件的缓存数据结构

打开的文件对应文件对象,如果文件被缓存了,该文件对象指向一个私有的缓存表结构,这个结构包含了最近两次读的位置,所以,缓存管理器可以执行智能预读,针对同一个文件的已打开实例的所有私有缓存表被链接在一起。

每一个被缓存的文件,都有一个共享的缓存表结构,描述了缓存的文件的状态,比如大小,有效的数据长度。同时,共享缓存表指向了由内存管理器所维护的内存区对象、与该文件相关联的私有缓存表的列表,以及VACB。

 

对于给定的文件,缓存管理器维护了一个VACB 指针数组,称为VACB 索引数组,第一项指向该文件的第一个256KB,第二个指向第二个256KB…

当一个进程访问一个特定文件的特定位置,找到正确的VACB 数组项,确定所请求的数据是否已经被映射到系统缓存中了。是,进行操作,否,在系统缓存中找到一个空闲槽,以映射所请求的视图。

 

当然,对于比较大的文件,以及特别大的文件,VACB索引数组的大小并不会相应的无线扩大。共享的缓存表包含了一个VACB 索引数组,含4个索引项,描述1MB。如果1MB<文件大小<32MB从非换页内存池中分配一个单独VACB 索引数组,大小为该文件的大小/256KB并向上取整。>32MB,从非换页内存池中分配的VACB 索引数组变成一个稀疏的多级索引数组,每个索引数组包含128项,一个文件所需要的级数:

(表示文件大小所需要的位数– 18)/7

 

文件系统访问文件的数据有三种方式:

 

从缓存中来回拷贝数据

因为系统缓存位于系统空间中,无法从用户模式中访问的,用户应用程序若要读写被缓存的文件,则必须通过内核模式的例程来获得服务:这些内核模式例程在“系统空间的缓存缓冲区”和“驻留在进程地址空间中的应用程序缓冲区”之间拷贝数据。被文件系统驱动程序用来执行这一操作的函数如下表

函数

说明

CcCopyRead

将指定的字节范围从系统缓存拷贝到用户緩冲区中

CcFastCopyRead

CcCopyRead的一个变形,更加快速,但也有限制:32位文件偏移,以及同 步读操作

CcCopy Write

将指定的字节范围从用户缓冲区拷贝到系统緩存中

 

CcFastCopyWrite

CcCopyWrite的一个变形,更加快速,但也有限制:32位文件偏移,以及同步的、非直写(non-write-through)的写操作(NTFS使用这种写糢式,FAT 不使用)

通过映射和锁定接□进行缓存

当用户应用程序读和写磁盘文件中的数据时,文件系统驱动程序需要读和写那些描述这些文件本身的数据(元数据,或者卷结构数据)。然而,由于文件系统驱动程序运行在内核模式 下,因此,如果缓存管理器被正确地通知到的话,这些文件系统驱动程序就可以直接修改系统缓存中的数据。为了允许这种优化,缓存管理器提供了表11.6中所示的函数。这些函数使得文件系统驱动程序可以找到文件系统的元数据驻留在虚拟内存中的什么地方,因此允许直接进行元数据修改,而无需使用中间缓冲区

寻找元数据位置的函数

函数

说明

CcMapData

为了读访问而映射一段字节范围

CcPinRead

为了读/写访问而映射一段字节范围,并锁定这段范围

CcPreparePinWrite

为了写访问(读访问不是有效的)而映射并锁定一段字节范围

CcPinMappedData

锁定一个原先已被映射的缓冲区

CcSetDirtyPinnedData

通知缓存管理器,此数据已被修改了

CcUnpinData

释故这些页面,因而它们可以被从内存中移除

 

 

如果一个文件系统驱动程序需要读缓存中的文件系统元数据,那么,它调用缓存管理器的映射接门来获得目标数据的虚拟地址。缓存管理器寻找所有被请求的页面,并把它们带入到内存中,然后将控制返回给文件系统驱动程序。于是,文件系统驱动程序可以直接访问这些数据

如果文件系统驱动程序需要修改缓存中的页面,那么,它调用缓存管理器的锁定服务,该服务会将这些被修改的页面保持在内存中。这些页面并不真的被锁在内存中(比如当设备驱动程序为了直接内存访问传输而锁住页面时所做的那样)。在绝大多数时间,文件系统驱动程序将它的元数据流标记为“不可写出(no write) •,这指示内存管理器的映射页面写出器不要将这些页面写出到磁盘上,直到明确地通知它可以写出为止当文件系统驱动程序解除锁定(释放)这些页面时,缓存管理器将所有的变化刷新到磁盘上,并且释放这些元数据所占据的缓存视图

映射和锁定接口解决了一个在实现文件系统时很棘手的问题:缓冲区管理。文件系统若不能直接操作被缓存的元数据,那么,它必须预测“当它更新一个卷的结构时”所需缓冲区的最大数量。由于允许文件系统直接访问和更新缓存中的元数据,因此,缓存管理器消除了对缓冲区的需求,文件系统只需简单地更新内存管理器所提供的虚拟内存中的卷结构即可。文件系统所碰到的惟一限制是,有多少内存可供使用。

通过直接内存访问接口进行缓存

直接内存访问(DMA)。通过DMA函数,可以直接读或写系统缓存的页面,而无需经由缓冲区的介入。

DMA接口将被缓存的用户数据的物理地址返回给文件系统,然后,这些物理地址可以直接被用于在物理内存和网络设备之间传输数据。

为了描述这些对于物理内存的引用,需要用到内存描述符列表(MDL)

函数

说明

CcMdIRead

返回一个描迷了指定字节范围的MDL

CcMdIReadComplete

释放MDL

CcMdIWrite

返回一个“描述一指定字节范围(可能包含了零)”的MDL

CcMdlWriteComplete

释放MDL,并将该范围标记为已被修改

        

快速 I/O

快速I/O是一种对于被缓存文件的读写方法,它无需经过“生成一个IRP”这样的环节。通过快速I/O, I/O管理器调用文件系统驱动程序的快速I/O 例程,以确定该I/O是否可以直接由缓存管理器来满足,而无需生成一个1RP。

因为缓存管理器是建立在虚拟内存子系统之上的,因此,文件系统驱动程序只需简单地对于“映射到实际被引用文件”的页面进行数据拷贝,就可以使用缓存管理器来访问文件数据,这样做也避免了生成一个IRP所需要的开销。

 

 

在用快速I/O 服务一个读或写操作的时候:

1.      线程执行读或者写操作

2.      如果文件已经缓存,且同步I/O,该请求被传递给文件系统驱动程序的快速I/O u入口点,如果文件尚未被缓存,文件系统驱动程序建立起该文件的缓存访问环境,因而下一次可以使用快速I/O 来处理一个读或写请求。

3.      如果文件系统驱动程序的快速I/O 例程确定快速I/O 是可能的,调用缓存管理器的读或写例程来直接访问缓存中的文件数据(如果快速I/O 不可能,生成一个IRP,并最终调用文件系统的常规读例程。

4.      .缓存管理器将所提供的文件偏移转译成缓存中的虚拟地址。

5.      对于读操作,缓存管理器将数据从缓存拷贝到发出该请求的进程的缓冲区中:对于写操作,它将数据从进程缓冲区拷贝到缓存中。

6.      以下动作之一发生:

对于读操作:若文件打开时未指定FILE_FLAG_RANDOM_ACCESS ,调用者的私有缓存表中的预读信息被更新

对于写操作:缓存中任何已修改页面的脏位被设置,因而延迟写出器将知道该把这些页面刷新到磁盘上

对于直写的文件(write-throungh file),任何修改都被刷新到磁盘上。

 

 

快速I/O 并不总是发生的

异步读写;同步I/O 上,文件系统驱动程序可以确定该I/O 不能用于快速I/O 机制来处理,如果所涉及的文件有一个锁定的字节范围(调用LockFile和 UnlockFile函数的结果),而缓存管理器不知道哪些文件的哪些部分被锁定了,文件系统驱动程序必须检查读写的有效性。

有关普通文件I/O 和映射文件I/O 的性能问题:

 

通过上面的介绍我们了解到,其实缓存管理器就是利用的内存区对象来实现类似于映射文件读写的过程,只不过,内存区对象的使用和维护是由操作系统控制的,而我们显式使用映射文件读写文件的时候自己控制了内存区对象的使用,比较直接,因此,一般文件的读写过程与内存映射文件读写数据的性能差距在于,缓存管理器需要将文件数据先拷贝到系统缓存中,然后再拷贝到用户提供的缓存区中,而内存映射文件可以直接将文件数据拷贝到用户缓存区中)。

下面这个博客做了验证性实验,读写磁盘数据较少(小于1MB)的时候,使用内存文件映射和普通IO 差异很小,大文件需要进行较为频繁的访问,或者一开始需要全部加载这些大文件的时候,就要考虑使用内存文件映射。

http://www.voidcn.com/blog/lishenglong666/article/p-1213219.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值