浅议Windows 2000/XP Pagefile组织管理
任何时候系统内存资源相对磁盘空间来说都是相形见拙的。因为虚拟内存机制,使我们可以有相对丰富的地址资源(通常32bit的虚拟地址,可以有4G的寻址 空间),而这些资源对物理内存来说一般情况是总是绰绰有余的。所以在现代操作系统中,总是在相对紧张时使用一些策略,如FIFO、LRU等将物理内存的一 些页面置入相对便宜的磁盘空间资源中。一般的UNIX系统,独立使用一个分区,即swap partition。而这方面Windows只是使用普通的文 件,通常命名为pagefile.sys,位于各分区的根目录中。由于受到用于pagefile的PTE的限制(PTE中使用4bit来识别操作的 pagefile),所以Windows最多可以支持16个pagefile.sys。
从上描述,pagefile.sys本身 就是一个比较特殊的文件,根据系统的情况它的大小是可扩展的,通常我们可以使用“控制面板”的“系统”小Applet来设置。由于其特殊性, Windows在启动阶段会对每个pagefile.sys建立相应的FILE_OBJECT,并且设置SharedRead字段为False,而且在 System进程,每个FILE_OBJECT都分别有一个句柄指向,这样即只允许系统自身对其操作,避免用户对其进行删除等误操作。
为了对pagefile.sys进行管理,Windows中有一个长度为16的数组,用于对pagefile.sys的组织。每个成员分别对应一个 pagefile。这个数组由系统变量MmPagingFile指向,每个成员都是一个指向MMPAGING_FILE的结构,这个结构有如下的格式:
+0x000 Size : Uint4B
+0x004 MaximumSize : Uint4B
+0x008 MinimumSize : Uint4B
+0x00c FreeSpace : Uint4B
+0x010 CurrentUsage : Uint4B
+0x014 PeakUsage : Uint4B
+0x018 Hint : Uint4B
+0x01c HighestPage : Uint4B
+0x020 Entry : [2] Ptr32 _MMMOD_WRITER_MDL_ENTRY
+0x028 Bitmap : Ptr32 _RTL_BITMAP
+0x02c File : Ptr32 _FILE_OBJECT
+0x030 PageFileName : _UNICODE_STRING
+0x038 PageFileNumber : Uint4B
+0x03c Extended : UChar
+0x03d HintSetToZero : UChar
+0x03e BootPartition : UChar
+0x040 FileHandle : Ptr32 Void
通 过这个结构,我们可以很容易的得到相应pagefile的使用情况(MaximumSize、MinimumSize、FreeSpace、 CurrentUsage、PeakUsage,请参阅windbg的!vm命令),其对应的FILE_OBJECT等。另外通过FILE_OBJECT 的DeviceObject与Vpb字段,我们就可知道这个pagefile所处的分区及分区使用的文件系统等等信息。我们来详细介绍一下Bitmap成 员。
Bitmap是一个RTL_BITMAP的结构,其定义在ntddk.h中:
typedef struct _RTL_BITMAP {
ULONG SizeOfBitMap; // Number of bits in bit map
PULONG Buffer; // Pointer to the bit map itself
} RTL_BITMAP;
与页框数据库(Pfn Database)与虚拟内存(x86平台PAGE_SIZE 4k)一样,Windows也将pagefile分割成4K一块块 的大小,称为一页,每页由Bitmap对应的1 bit指定状态。1为占用,0为空闲。通过使用RtlFindClearBits或是 RtlFindClearBitsAndSet等函数对Bitmap进行操作,寻找这些文件的未用页面。虽然Bitmap指明占用状态时,Windows 常以4k为单位,但为了提高性能,Windows在一次写pagefile的单位通常为64k(MmModifiedWriteClusterSize个 页)。还有MMMOD_WRITER_MDL_ENTRY,等我下面提及相关内容时再加以说明。
先用windbg来消化一下上面的讨论:
kd> dd MmPagingFile l 10 //从输出结果可以看出我的机子上设了两个pagefile。
80547020 80d2af80 feec1548 00000000 00000000
80547030 00000000 00000000 00000000 00000000
80547040 00000000 00000000 00000000 00000000
80547050 00000000 00000000 00000000 00000000
kd> dd @$p l 40 //第一个pagefile的情况。
80d2af80 00006400 0000c800 00006400 00000c38
80d2af90 000057c7 000057c7 00000000 00000000
80d2afa0 feea1cb8 feea1c18 fecbb000 feddc428
.
.
.
kd> dd feddc428 l 4 //从上面给出的MMPAGING_FILE,很容易得到file object(Offset 0x2c)。
feddc428 00700005 80ecf2f0 80ecf268 fee66c10
kd> !devobj 80ecf2f0 //aFILE_OBJECT的结构在ntddk.h中给出,其第三个dword就是DEVICE_OBJECT。
Device object (80ecf2f0) is for:
HarddiskVolume2 \Driver\Ftdisk DriverObject 80d97030
Current Irp 00000000 RefCount 1316 Type 00000007 Flags 00001150
Vpb 80ecf268 Dacl e13d1484 DevExt 80ecf3a8 DevObjExt 80ecf490 Dope 80ecf210 DevNode 80d95bd0
ExtensionFlags (0000000000)
AttachedDevice (Upper) 80d954b8 \Driver\VolSnap
Device queue is not busy.
另外FILE_OBJECT的第四个dword(fee66c10)就是VPB结构,你使用!vpb分析分析,限于篇幅,我就不在这儿列出了。
通过上面windbg的分析,我们已经基本上对pagefile有了一定的了解了,下面转入内存子系列与IO子系统(调用FSD)对pagefile的组织管理。
通常情况下,对于进程可见的永远是虚拟地址,存取某个虚拟地址,对于不存在的地址(对于X86,即其PTE的P位为0),通过触发硬件中断(X86为 int e),由软件来对这些PTE进行解析,譬如原型PTE(我在《探究Windows 2000/XP原型PTE》中详细介绍),或是过渡PTE (Transition PTE,某些页面由于进程工作集修整等原因,成为可被使用的页面,但这些页面的内容当前对这些进程仍有效,可随时重新使用,所以 Windows使用Transition这个术语区别于纯粹的Free或Zeroed列表,我在《解析Winndows 2000/XP物理内存管理》中 提及PFN列表)等,而对于Page File,实际上也有一个对应的pte指向相应pagefile.sys,完成解析工作 (MiResolvePageFileFault),处理页面错误(通过IoPageRead,下面会介绍)。
所以在继续讨论之前我们来说明一下Pagefile PTE,它的格式如下:
Valid : Pos 0, 1 Bit
PageFileLow : Pos 1, 4 Bits
Protection : Pos 5, 5 Bits
Prototype : Pos 10, 1 Bit
Transition : Pos 11, 1 Bit
PageFileHigh : Pos 12, 20 Bits
对于Prototype PTE与Transition PTE,总有1bit用于识别相应的PTE,如上的Prototype字段,但对于 PageFile PTE,却没有对应的识别bit,实际上MiDispatchFault(由KiTrap0E调用),是在解析完 Prototype PTE(MiResolveProtoPteFault)、Transition PTE (MiResolveTransitionFault)、还有MiResolveDemandZeroFault后,才调用 MiResolvePageFileFault的,当然在MiResolveProtoPteFault处理过程中也是最后调用 MiResolvePageFileFault的。
假设我们存取一个当前驻留在pagefile中的页面,通过 MiDispatchFault,控制权转到MiResolvePageFileFault后,他会根据PTE的PageFileLow来索引 MMPAGING_FILE数组,即判断这一页面位于哪个pagefile.sys中,因为PageFileLow为4个bit,所以Windows最多 可以支持16个pagefile.sys。这样内存子系统根据这个索引从MmPagingFile中描述的页文件结构取出这个pagefile的 FILE_OBJECT(上面介绍过)。加上PageFileHigh所指定的pagefile.sys的偏移值, MiResolvePageFileFault通过返回一个值为0xC0033333的特殊NTSTATUS通知MiDispatchFault调用 IoPageRead得到此页面。IoPageRead的原型如下(定义于ntifs.h中):
NTKERNELAPI
NTSTATUS
IoPageRead(
IN PFILE_OBJECT FileObject,
IN PMDL MemoryDescriptorList,
IN PLARGE_INTEGER StartingOffset,
IN PKEVENT Event,
OUT PIO_STATUS_BLOCK IoStatusBlock
);
当然在调用IoPageRead之前,内存管理器必须分配一个物理页面,必要的时候还要调用MiRemoveAnyPage腾出空间,然后调用 MiInitializeReadInProgressPfn,将这一页框置成ReadInProgress状态,然后将IoPageRead所需要的 MDL参数MemoryDescriptorList指向这一页面。MDL的虚拟地址字段也就是IoPageRead读入的页面映射的虚拟地址,也即满足 我们先前假设的页面错误。
IoPageRead实际上通过Allocate一个IRP,用DIRECT_IO的方式(即我们提供 的MDL),然后设置一个Complete Routine,用于取消页面读取之前的ReadInProgress状态,再通过IoCallDriver 调用IO子系统调用对应的File System Driver(通常由FILE_OBJECT的VPB参数确定),至于FSD是如何读取 pagefile.sys的,这儿不加以讨论,ntifs提供的fastfat的源代码是学习的方向。
需要指出的是 IoPageRead是一个同步操作,即只有等待页面读完毕以后才可以往下处理。这也是MiDispatchFault只能运行于 DISPATCH_LEVEL IRQL之下的主要原因。IoPageRead通过设备分配的IRP的 IRP_SYNCHRONOUS_PAGING_IO的标志来实现同步的。另外他也设置了IRP_PAGING_IO、IRP_NOCACHE标志,用于 与FSD之间的特殊通信要求。
由于工作集修整等的需要,通过MiModifiedPageWriter(MPW)线程实行将某些 页面置入pagefile中。MPW使用MMPAGING_FILE结构的_MMMOD_WRITER_MDL_ENTRY类型的Entry进行操作, _MMMOD_WRITER_MDL_ENTRY不仅仅由MiModifiedPageWriter使用,他还要让MiMappedPageWriter 使用(用于Mapped file),所以_MMMOD_WRITER_MDL_ENTRY结构不仅函有MDL成员,还包含Control Area等 等。限于篇幅,我不将其结构列出。MPW通过IoAsynchronousPageRead将页面按前面说的一次 MmModifiedWriteClusterSize个页面写入pagefile中。对于IoAsynchronousPageRead其使用的 IRP flag是IRP_PAGING_IO与IRP_NOCACHE,说明他是异步操作的。这也可从他的名字看出,区别于Windows提供的另一个 相关过程IoSynchronousPageWrite,他是同步的。
讲到这儿,对于page file的组织管理的一些基本的 印象应该是有的。最后需要指出的一点是,对于IoPageRead不仅仅是对于pagefile的,其也可以针对mapped file,还有 MiModifiedPageWriter,要不是避免死锁也不会区分出MiMappedPageWriter,实际上Windows内部内存管理器对于 pagefile与mappedfile的管理使用是基本相同的,而FSD的处理也只是一点点的区别而已。所以结合我以前介绍的如 Control Area等概念,对mapped file等的理解也是可以参照本文的。还有同样的一句话,错误地方希望得到你的指点。
浅议Windows 2000/XP Pagefile组织管理的更多相关文章
- 浅议Delphi中的Windows API调用(举的两个例子分别是String和API,都不错,挺具有代表性)
浅议Delphi中的Windows API调用http://tech.163.com/school • 2005-08-15 10:57:41 • 来源: 天极网为了能在Windows下快速开发应用程 ...
- OD: Heap in Windows 2K & XP SP1
Windows 堆溢出 MS 没有完全公开 Windows 的堆管理细节,目前对 Windows 堆的了解主要基于技术狂热者.黑客.安全专家.逆向工程师等的个人研究成果. 目前 Windows NT4 ...
- Windows Server Core Command (管理服务器核心的具体操作命令)
从 Windows Server 2008 开始,管理员可以选择安装具有特定功能但不包含任何不必要功能的 Windows Server 的最小安装服务器核心(Server Core),它为一些特定服务 ...
- 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍
浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...
- 浅议Grpc传输机制和WCF中的回调机制的代码迁移
浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...
- 浅议.NET遗留应用改造
浅议.NET遗留应用改造 TLDR:本文介绍了遗留应用改造中的一些常见问题,并对改造所能开展的目标.原则.策略进行了概述. 一.背景概述 1.概述 或许仅"遗留应用"这个标题就比较 ...
- 为了体验 ILS 在Win2012R2 Hyper-V上安装Windows 2000 AdvSer
Win2012 R2 Hyper-V 的集成服务包已不支持Windows 2000 先安装SP4.IE6.更新汇总包,再来安装这个. 安装完成后,会有几个未知设备,直接禁用就可以了. 开启Window ...
- Windows编程中的堆管理(过于底层,一般不用关心)
摘要: 本文主要对Windows内存管理中的堆管理技术进行讨论,并简要介绍了堆的创建.内存块的分配与再分配.堆的撤销以及new和delete操作符的使用等内容. 关键词: 堆:堆管理 1 引言 在大多 ...
- [Oracle] UNIX与Windows 2000上Oracle的差异(III)
作者:Ian Adam & David Stien, SAIC Ltd 日期:19-Dec-2003 出处:http://www.dbanotes.net翻译:Fenng ORACLE 的安装 ...
随机推荐
- java FileUtils 文件工具类
package com.sicdt.library.core.utils; import java.io.BufferedInputStream; import java.io.File; impor ...
- 利用CXF框架开发webservice
开发服务端代码 1. web.xml文件中添加cxf的servlet 2. 定义接口 @WebService(targetNamespace="http://UserInfo.ws.com& ...
- MVC 中 System.Web.Optimization 找不到引用
在MVC4的开发中,如果创建的项目为空MVC项目,那么在App_Start目录下没有BundleConfig.cs项的内容,在手动添加时在整个库中都找不到:System.Web.Optimizatio ...
- Educational Codeforces Round 15 A, B , C 暴力 , map , 二分
A. Maximum Increase time limit per test 1 second memory limit per test 256 megabytes input standard ...
- php提前输出响应及注意问题
1.浏览器和服务器之间是通过HTTP进行通信的,浏览器发送请求给服务器,服务器处理完请求后,发送响应结果给浏览器,浏览器展示给用户.如果服务器处理请求时间比较长,那么浏览器就需要等待服务器的处理结果. ...
- 10.0.4_CentOS_120g_for_Qt5.3.2
对应 VMware Workstation 版本为:“10.0.4 build-2249910”
- value optimized out的问题
看redis源码,查看某个变量的值的时候出现:value optimized out 变量被编译优化掉了,看不到了. 解决方法: 在编译redis的时候,make添加参数.0表示编译的时候不对代码进行 ...
- BZOJ 2425 [HAOI2010]计数:数位dp + 组合数
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2425 题意: 给你一个数字n,长度不超过50. 你可以将这个数字: (1)去掉若干个0 ( ...
- dp3--codevs2598 编辑距离问题
dp3--codevs2598 编辑距离问题 一.心得 1.字符串相关问题dp的时候从0开始是个陷阱 二.题目 2598 编辑距离问题 时间限制: 1 s 空间限制: 128000 KB 题目等 ...
- compile to 32-bit elf file
nasm -f elf -o a.o a.asm gcc -c -m32 -o b.o b.c ld -s -m elf_i386 -Ttext 0x30400 -o b.bin b.o a.o