windows内存管理2(做双缓存透明加密驱动必看)

来源:互联网 发布:淘宝一天可以刷几单 编辑:程序博客网 时间:2024/05/18 20:47

这些东西我整理出来很久了,由于各种原因一直没放出来,引用的图来自网络或者书籍,如果你看的不错想要转载请注明本空间。

接上文:

*文件缓存分

一个典型文件创建缓存过程:

1.当文件对象第一次被缓存读写时,文件系统调用CcInitializeCacheMap初始化缓存

2.如果FileObject->SectionObjectPointer->SharedCacheMap== NULL ,从NonPagedPool分配SharedCacheMap,初始化其中一部分域。

3.调用MmCreateSection创建SharedCacheMap->Section,MmCreateSection中:

l       首先检查是否FileObject->SectionObjectPointer->DataSectionObject已经存在

l       没有存在从NonPagedPool分配一个NewControlArea大小为ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION),设置到FileObject->SectionObjectPointer->DataSectionObject

l       创建Segment,这里以MiCreateDataFileMap为例子:

     *检查CcInitializeCacheMap传入的文件占用大小是不是大于系统定义的最大Section大小,计算文件需要的pte数量

     *PagedPool创建NewSegment,类型是MAPPED_FILE_SEGMENT,然后把源文件打散成许多块(Subsection)

     *在NonPagedPool中分配Subsection链接在NewControlArea后面

     *初始化NewControlArea剩下的域,得到第一个Subsection,设置其中域,找到所有的Subsection初始化他们

l       创建SECTION对象,并且初始化

4.创建Section完成后,如果是streamobject是不可能被映射的,这时候关闭modwrite标志

5.调用CcCreateVacbArray创建VACB索引数组

6.………….

当缓存创建完成后, 如果收到CcCopyRead

1.  首先先用GetActiveVacb找到是否落在活动视图内,如果没有落在活动视图内调用CcGetVirtualAddress取得地址:

l       用GetVacb取得FileOffset处的VACB,如果为NULL就调用CcGetVacbMiss从CcVacbFreeList中获得一个没有用的VACB

l       调用MmMapViewInSystemCache映射视图到系统缓存:

    *得到需要多少页面NumberOfPages,计算PteOffset与LastPteOffset

    *LOCK_PFN锁定PFN,提升DPC,得到第一个空闲的系统缓存地址保存到 PointerPte ,更新第一个空闲地址MmFirstFreeSystemCache

    *如果ControlArea->FilePointer不为空,调用MiAddViewsForSection分配原型pte(MappedSubsection->SubsectionBase = ProtoPtes)

    *得到VACB对应缓存buffer的PointerPte的虚拟地址,设置相应的值(设置成原形PTE),返回

l       设置这个VACB相应值并返回

 

2. 得到了VACB对应CacheBuffer,按照页大小分几次操作.

3. 校验内存是否是有效的地址,调用MmCheckCachedPageState:

l       得到地址SystemCacheAddress的PTE(MiGetPteAddress()),根据PTE得到对应原形PTE(MiPteToProto())

l      如果无效的调用MmAccessFault,MmAccessFault校验PDE,PTE,这里会得到PTE对应原形PTE然后调用MiDispatchFault去解决这个地址错误

    *MiDispatchFault内部调用MiResolveProtoPteFault解决原形pte错误(注意PFN项的颜色,这里调用MiRemoveAnyPage得到一个物理页面).

    *这里详细看下MiResolveProtoPteFault取得物理页面过程:

    ①MiGetInPageSupportBlock先分配一个读取块ReadBlockLocal,得到ReadBlockLocal->Page[0]地址.

    ②计算出EndPage = Page + ClusterSize,

    ③取得pte的颜色,根据颜色调用MiRemoveAnyPage取得物理页帧给ReadBlock->Page中每个成员赋值

    ④调用MiInitializeReadInProgressPfn初始化指定的pfn项成为转移,正在读入状态,设置原形pte为转移状态,指向物理页面

    *调用完成MiResolveProtoPteFault后,原形pte设置成转移状态,pte指向物理页面,物理页面被设置成正在转移读入状态,这时候我们需要读入内容(STATUS_ISSUE_PAGING_IO)

    *调用IoPageRead发出pagingio读入内容


还是继续看图吧,画的很清楚了:

xp下解析一个文件映射结构

1.        直接创建一个文件映射,FileObjectDataSectionObject被赋值

kd> dt 0x81c2fd50_SECTION_OBJECT_POINTERS

ntdll!_SECTION_OBJECT_POINTERS

  +0x000 DataSectionObject : 0x81cb3fa0Void

  +0x004 SharedCacheMap   : (null)

  +0x008 ImageSectionObject : (null)

 

kd> dt _CONTROL_AREA 0x81cb3fa0

nt!_CONTROL_AREA

  +0x000 Segment          : 0xe19092e0 _SEGMENT

  +0x004 DereferenceList  :_LIST_ENTRY [ 0x0 - 0x0 ]

  +0x00c NumberOfSectionReferences : 1

  +0x010 NumberOfPfnReferences : 0x10

   +0x014NumberOfMappedViews : 1

  +0x018 NumberOfSubsections : 1

  +0x01a FlushInProgressCount : 0

  +0x01c NumberOfUserReferences : 2

  +0x020 u                :__unnamed

  +0x024 FilePointer      :0x820bdef0 _FILE_OBJECT

  +0x028 WaitingForDeletion : (null)

  +0x02c ModifiedWriteCount : 0

  +0x02e NumberOfSystemCacheViews : 0

               kd> dt 0xe19092e0_SEGMENT

nt!_SEGMENT

  +0x000 ControlArea      :0x81cb3fa0 _CONTROL_AREA

  +0x004 TotalNumberOfPtes : 0x10

  +0x008 NonExtendedPtes  : 0x10

  +0x00c WritableUserReferences : 2

  +0x010 SizeOfSegment    : 0x10000

  +0x018 SegmentPteTemplate : _MMPTE

  +0x020 NumberOfCommittedPages : 0

  +0x024 ExtendInfo       : (null)

  +0x028 SystemImageBase  : (null)

  +0x02c BasedAddress     : (null)

  +0x030 u1               :__unnamed

  +0x034 u2               :__unnamed

  +0x038 PrototypePte     :0x00020208 _MMPTE

  +0x040 ThePtes          : [1]_MMPTE

2.        NumberOfSubsections=1看出被打散成一块,注意

kd> dt _SUBSECTION 0x81cb3fa0+2e+2

nt!_SUBSECTION

  +0x000 ControlArea      : 0x81cb3fa0 _CONTROL_AREA

  +0x004 u                :__unnamed

  +0x008 StartingSector   : 0

  +0x00c NumberOfFullSectors : 0x10

  +0x010 SubsectionBase   :0xe2072aa8 _MMPTE

  +0x014 UnusedPtes       : 0

  +0x018 PtesInSubsection : 0x10

  +0x01c NextSubsection   : (null)

关于缓存的结构:

VACB被设计成了索引形式:

除了VACB外,还有一个用于表示锁定的内存(pin)的形式:

值得注意的是系统用512k也就是vacb视图的2倍大小来管理BCB视图。

512k就在共享缓存视图的BcbList中加入一个LIST_ENTRY结构作为链表的头

kd> dt _SHARED_CACHE_MAP0x82404008

nt!_SHARED_CACHE_MAP

   +0x000 NodeTypeCode     : 0n767

   +0x002 NodeByteSize     : 0n304

   +0x004 OpenCount        : 1

   +0x008 FileSize         : _LARGE_INTEGER 0x1490000

   +0x010BcbList          : _LIST_ENTRY [0x8269d2a0 - 0x8269d158 ]

   +0x018 SectionSize      : _LARGE_INTEGER 0x1500000

   +0x020 ValidDataLength  : _LARGE_INTEGER 0x7fffffff`ffffffff

   +0x028 ValidDataGoal    : _LARGE_INTEGER 0x7fffffff`ffffffff

   +0x030 InitialVacbs     : [4] (null)

   +0x040 Vacbs            : 0x8269d008  -> 0x827813f0 _VACB

   +0x044 FileObject       : 0x82799220 _FILE_OBJECT

   +0x048 ActiveVacb       : (null)

   +0x04c NeedToZero       : (null)

   +0x050 ActivePage       : 0

   +0x054 NeedToZeroPage   : 0

   +0x058 ActiveVacbSpinLock : 0

   +0x05c VacbActiveCount  : 2

   +0x060 DirtyPages       : 9

   +0x064 SharedCacheMapLinks : _LIST_ENTRY [0x8206f204 - 0x8089d290 ]

   +0x06c Flags            : 0x605

   +0x070 Status           : 0n0

   +0x074 Mbcb             : (null)

   +0x078 Section          : 0xe1958410 Void

   +0x07c CreateEvent      : (null)

   +0x080 WaitOnActiveCount : (null)

   +0x084 PagesToWrite     : 0

   +0x088 BeyondLastFlush  : 0n20500480

   +0x090 Callbacks        : 0xf719e64c _CACHE_MANAGER_CALLBACKS

   +0x094 LazyWriteContext : 0x82641cf0 Void

   +0x098 PrivateList      : _LIST_ENTRY [ 0x8240412c - 0x8240412c ]

   +0x0a0 LogHandle        : 0xe17d4140 Void

   +0x0a4 FlushToLsnRoutine : 0xf71b5870     void Ntfs!LfsFlushToLsn+0

   +0x0a8 DirtyPageThreshold : 0

   +0x0ac LazyWritePassCount : 0x141

   +0x0b0 UninitializeEvent : (null)

   +0x0b4 NeedToZeroVacb   : (null)

   +0x0b8 BcbSpinLock      : 0

   +0x0bc Reserved         : (null)

   +0x0c0 Event            : _KEVENT

   +0x0d0 VacbPushLock     : _EX_PUSH_LOCK

   +0x0d8 PrivateCacheMap  : _PRIVATE_CACHE_MAP

 

kd> dc 0x8269d158  这块内存分配的大小是文件大小/512k*8

8269d158 82404018 8269d160 8269d158 8269d168 .@@.`.i.X.i.h.i.

8269d168 8269d160 8269d170 8269d168 827098b0 `.i.p.i.h.i...p.

8269d178 827098b0 8269d180 8269d178 8269d188 ..p...i.x.i...i.

8269d188 8269d180 8269d190 8269d188 81ce0cd0  ..i...i...i.....

8269d198 81ce0cd0 8269d1a0 8269d198 8269d1a8  ......i...i...i.

8269d1a8 8269d1a0 8269d1b0 8269d1a8 8269d1b8 ..i...i...i...i.

8269d1b8 8269d1b0 8269d1c0 8269d1b8 8269d1c8 ..i...i...i...i.

8269d1c8 8269d1c0 8269d1d0 8269d1c8 8269d1d8 ..i...i...i...i.

 

上面红色的为插入的一个BCB项: 注意bcb是按照FileOffset降序插入的。

kd> dt nt!_BCB 81ce0cc0

  +0x000 Dummy            : _MBCB

  +0x000 NodeTypeCode     : 0n765

  +0x002 Dirty            : 0x1 ''

  +0x003 Reserved         : 0 ''

  +0x004 ByteLength       : 0x1000

  +0x008 FileOffset       :_LARGE_INTEGER 0x3d3000

  +0x010 BcbLinks         :_LIST_ENTRY [ 0x8269d190 - 0x8269d198 ]

  +0x018 BeyondLastByte   :_LARGE_INTEGER 0x3d4000

  +0x020 OldestLsn        :_LARGE_INTEGER 0x2c1c6a65

  +0x028 NewestLsn        :_LARGE_INTEGER 0x2c1c6e13

  +0x030 Vacb             : (null)

  +0x034 PinCount         : 0

  +0x038 Resource         :_ERESOURCE

  +0x070 SharedCacheMap   : 0x82404008 _SHARED_CACHE_MAP

  +0x074 BaseAddress      : (null)

Pin的作用是锁定内存保证修改后不会被修改页面写出器与映射页面写出器写出。

0 0