想深入了解文件系统Cache管理器 | |
---|---|
http://www.sina.com.cn 2006年01月24日 13:43 天极yesky | |
我以前不大明白Windows的文件系统和缓冲管理器之间的关系。仅仅知道Cc开头的系列调用是缓冲管理器提供的,文件系统中可以调用。也知道缓冲对于文件系统的意义,在于缓冲读写操作,使磁盘得到高效的利用。 为了翻译了这些资料,我也大致明白了文件系统和缓冲管理器之间的互动。windows的文件系统和缓冲管理器之间是相互调用的关系,双向沟通。总的来说,是缓冲管理器提供一些调用给文件系统,文件系统注册一些回调函数给缓冲管理器,而且缓冲管理器会发IRP给文件系统来处理。 首先文件系统如果想要实现缓冲读写,那么肯定要调用缓冲管理器提供的调用。(如对于缓冲读,不直接自己读磁盘,而是调用CcCopyRead),但是缓冲管理器自然还是要通过文件系统来实际读磁盘。因此缓冲管理器会发出IRP来给文件系统进行处理。这样,文件系统就要分别缓冲管理器发来的请求和用户进程发来的请求分别处理了。 把不同的请求放在同一个例程中处理,这正是设计上最令人恼火的地方。不过理解了这一点之后,你也就大致明白缓冲管理器和文件系统是如何交互的了。 NT 文件系统缓冲管理器 所以Window NT 缓冲管理器的一个关键优点,就是允许我们在文件系统缓冲和程序运行使用物理内存之间保持一个平衡.当一个应用正在消耗内存,用来进行文件数据缓冲的内存可能被缩减到接近0.结果系统让物理内存得到了更好的使用,最终提供了更好的性能. 文件系统还有一个使用Cache管理器的关键原因.一个文件可能被标准的文件系统接口访问.比如读和写,也有可能通过内存管理器被做为内存映射文件访问.有时两种访问方式被用在同一个文件上.这是Cache管理器提供一个机制,建立这两种访问方式之间的桥梁,以确保数据的可靠性. Cache管理器数据结构 文件系统和Cache管理器之间的接口是一种过程上的接口.所有的Cache管理器用到的数据结构,有必要通过一个文件联系起来.但是实际上这些内部接口对文件系统是透明的.在这里我们描述这些文件系统和Cahce管理器共享的关键的数据结构. 缓冲控制块(BCB,Buffer Control Block) 如果一个文件的一部分被映射到一个系统内存地址,Cahce管理器内部使用缓冲控制块来记录.有时文件系统进行某些临界操作的时候,需要在内存中锁定一些数据.所以这个结构必须暴露给文件系统使用: 缓冲控制块的大部分是部可见的.开头的一部分暴露给文件系统: typedef struct _PUBLIC_BCB { CSHORT NodeTypeCode; CSHORT NodeByteSize; ULONG MappedLength; LARGE_INTEGER MappedFileOffset; } PUBLIC_BCB,*PPUBLIC_BCB; 开始的两个域是Windows数据结构的标准域,说明数据结构的类型和长度.后边的两个域是文件系统感兴趣的,说明了这个文件被这个特殊的缓冲控制块所管理的内容范围. 文件大小信息 文件系统和内存管理器都维护文件大小的信息.当文件系统建立了一个文件的映射,它记录了文件的当前大小.以后的任何改动同样被提交给Cache管理器. Cache管理器用三个值用来表示文件的大小: typedef struct _CC_FILE_SIZES { LARGE_INTEGER AllocationSize; LARGE_INTEGER FileSize; LARGE_INTEGER ValidDataLength; } CC_FILE_SIZES,*PCC_FILE_SIZES; 这些域的名字容易混淆.比如AllocationSize不是说给这个文件分配实际的物理空间,而是当前已经分配的空间中能容纳的数据总量.对一般的文件系统来说,上边两个数据当然应该是一样的.但是,对一个支持数据压缩或者扩展的文件系统而言,这个值表示当前控件中所能容纳的数据量(而不是空间大小). AllocationSize被内存管理器用来得到section object.section object被用来觉得一个文件是如何映射到内存的,所以AllocationSize总是至少和文件一样大.缓冲管理器和内存管理起没有考虑当文件系统把AllocationSize设置得比file size小的情况.系统会因数据结构的混乱而崩溃. FileSize表示了文件数据中最后一个有效的字节的位置,一般是文件结束标记. |