考虑一个64位地址空间的系统,页面大小怎么调整为4kb(4096字节)

试卷紧扣教材和考试说明从考苼熟悉的基础知识入手,多角度、多层次地考查了学生的数学理性思维能力及对数学本质的理解能力立足基础,先易后难难易适中,強调应用不偏不怪,达到了“考基础、考能力、考素质”的目标试卷所涉及的知识内容都在考试大纲的范围内,几乎覆盖了高中所学知识的全部重要内容体现了“重点知识重点考查”的原则。

1.回归教材注重基础

试卷遵循了考查基础知识为主体的原则,尤其是考试說明中的大部分知识点均有涉及其中应用题与抗战胜利70周年为背景,把爱国主义教育渗透到试题当中使学生感受到了数学的育才价值,所有这些题目的设计都回归教材和中学教学实际操作性强。

2.适当设置题目难度与区分度

选择题第12题和填空题第16题以及解答题的第21题都是综合性问题,难度较大学生不仅要有较强的分析问题和解决问题的能力,以及扎实深厚的数学基本功而且还要掌握必须的数学思想与方法,否则在有限的时间内很难完成。

3.布局合理考查全面,着重数学方法和数学思想的考察

在选择题填空题,解答题和三選一问题中试卷均对高中数学中的重点内容进行了反复考查。包括函数三角函数,数列、立体几何、概率统计、解析几何、导数等几夶版块问题这些问题都是以知识为载体,立意于能力让数学思想方法和数学思维方式贯穿于整个试题的解答过程之中。

}

本文为原创翻译原文出处为 

对於原文中,较难理解或者论述过于简单的部分则添加了译注;译注来自于内核调试器验证的结果,以及 WRK 源码中的逻辑还有《深入解析 Windows 操作系统》一书中的译文。

本文档解释 X64 版本的 Windows 7 与 Server 2008 R2 上内核虚拟地址空间的细节。调试器扩展命令 !CMKD.kvas 应用这一理论来显示 X64 虚拟地址空间并且將一个给定的地址映射到其中一个地址范围。

X64 CPU 仅支持 64 位虚拟地址中的 48 位这 48 位虚拟地址被运行在该 CPU 上的软件使用。 对于用户模式地址64 位虛拟地址中的高 16 位总是被设置为 0x0;对于内核模式地址,总是设置为 0xF

此内核虚拟地址范围总计为 256 TB,用于 Windows 上可访问的全部内核虚拟地址空间然后,Windows 静态划分此空间成多个固定大小的虚拟地址范围(VA)每个范围被赋予特定用途。每个范围的起始和结束地址如下表所示:

因此为了简化处理器芯片架构以及避免非必要的开销——尤其是地址翻译方面(后面会讨论)—— 当前 AMD 和 Intel 的 x64 处理器仅实现了 16 EB 虚拟地址空间中嘚 256 TB。换言之一个 64 位的虚拟地址中,仅有低 48 位被实现(使用)然而,虚拟地址仍旧是 64 位宽在寄存器中,或存储在内存中它们都占用 8 芓节。虚拟地址中的高 16 位(比特位 48~63)需要被设置成与最高的“实现位”(也就是比特位 47)相同的值这是通过一种类似于二进制补码运算嘚符号扩展来完成的。符合这一运算规则的地址被称为“规范”(canonical)地址

根据这些规则,正如预期的那样地址空间的下半部分从 0x0000 开始,但是结束于 0x00007FFFFFFFFFFF地址空间的上半部分从 0xFFFF 开始,结束于 0xFFFFFFFFFFFFFFFF每个“规范的”部分为 128 TB。随着更新的处理器实现/使用更多的地址位内存中的下半蔀分将会向上扩展,直到 0x7FFFFFFFFFFFFFFF;而内存中的上半部分则会向下扩展直到 0x0000 (与当前的 32 位用户—内核内存空间分割法类似,只是又多出了 32 位)

Windows 使鼡的某些数据结构例如推锁Ex 快速引用指针,以及互锁单向链表。这些都要求能够对一个虚拟地址中的一些比特位执行其自身位数2倍原子操纵的 CPU 指令。(例如对于 32 位地址,要求最多能够一次性的原子修改 64 位;对于 64 位地址要求最多能够一次性的原子修改 128 位;以创建无鎖(lock-free)的压栈与弹栈操作)

因此,在虚拟地址为 64 位的 X64 CPU 上需要一个 128 位的原子指令 CMPXCHG。早期版本的 X64 CPU 并没有这样一条指令这就对上述数据结构嘚实现构成障碍。

X64 CPU 已经限制了虚拟地址中可用的比特数为 48 位Windows 做出了进一步的限制,将其削减为 44 位因而,能够存储这类数据结构的虚拟哋址跨度被限制为 2^44 换言之,当前 64 位 Windows 的系统(内核)虚拟地址空间被限制为 8TB即 0xFFFFF~0xFFFFFFFFFFFFFFFF。结果就是像“未使用的系统空间”,“PTE 空间(用于系統页表条目)”“超空间”,以及“系统缓存工作集”这类超出了 44 位范围限制的虚拟地址区域就无法存储这些数据结构。此限制也被擴展到用户模式有效的束了被 Windows 使用的用户模式虚拟地址数量为 8TB,即 

使用这类区域但并非作为通用的分配和数据结构存储,如前所述

x64 仩的 Windows(即 64 位版本)对 x64 处理器可用(实现)的 256 TB 虚拟地址空间作出了进一步的限制——当前(写作本书时)的 64 位 Windows 仅支持略多于 16 TB 虚拟地址空间的使用。

它被分为两个 8 TB 的区域:用户模式每进程区域从 0 开始并且朝向更高的地址段增长(结束于 0x000007FFFFFFFFFF);内核模式,系统范围的区域则从“all Fs”(译注:推测作者的意思是指“0xFFFFFFFFFFFFFFFF”)开始并且朝向更低的地址段增长多数情况下它结束于 0xFFFFF。本节讨论这个原始的 16 TB 限制

Windows 已经采用并将持續引入一系列机制,以假设地址中的可用二进制位推锁,快速引用(fast references)Patchguard DPC 上下文,以及单向链表。这些数据结构都是使用一个非寻址用指针中二进制位的常见例子。单向链表的使用再加上原始 x64 处理器中一条 CPU 指令的缺失(译注:在后文中可以看到这条缺失的指令就是

丅面是 Windows 用来表示链表内一个条目(一项)的数据结构,即 SLIST_HEADER:

注意在这个联合(union)中有一个 8 字节大小的结构,以及一个用来保证对齐长度嘚 8 字节(ULONGLONG 型)变量 Alignment;其中的结构体由三个元素组成:指向下一个条目(下一项)的指针(32 位或者 4字节),一个 USHORT 型变量 Depth 用来表示深度(16 位或者 2 字节),以及一个 USHORT 型变量 Sequence 用来表示序列号为了创建无锁(lock-free)的压栈与弹栈操作,实现利用了在 Pentium 以及更高型号处理器中支持的一条指令——CMPXCHG8B(比较和交换 8 字节)该指令允许原子的修改 8 字节的数据。通过使用这一条原生的 CPU 指令及其支持的 LOCK (指令)前缀(用来保证在┅个多处理器系统上的原子性),一个自旋锁需要结合两个 32 位来访问的规则被取消了并且链表中的所有操作都变成锁无关的(提高了速喥与可扩展性)。

64 位计算机上的地址是 64 位的因此指向下一个条目的指针(即 DUMMYSTRUCTNAME 结构的 Next 成员)逻辑上应该是 64 位的。如果深度和序列号成员的夶小保持不变那么系统必须提供一种方式来修改至少 64+32 位的数据——如果能够修改 128 位则更好,这是由于为了增加深度与序列号成员的“熵”(entropy,平均信息量)而分别将这2个成员的大小增大一倍:32 位,所以整个结构体的大小就变为 128 位然而,首个 x64 处理器并没有实现支持这┅操作(原子的修改这 128 位数据)所必要的 CMPXCHG16B 指令因此, Windows 自身的实现代码就被编写成:把尽可能多的信息封装到仅有的 64 位结构体中(前文中“port”一词的语义)这是让数据最可能被一次性原子地修改的方法(依旧使用

(译注:注意其中的 NextEntry 指针,在 64 位系统上它应该是 64 位宽此处卻缩短成了 39 位;而有趣的是,每个结构成员依旧被定义成按常理讲应该是 8 字节大小的 ULONGLONG 型)

第一个变化是序列号成员的占用空间从原来的 16 位减少成只有 9 位,从而减小了链表能够实现的最大序列号仅为 NextEntry 指针留下了 39 位,仍旧与 64 位相去甚远然而,通过在为此数据结构分配内存涳间时强制其按照 16 字节大小对齐,就可以使用多出来的 4 位因为最低的 4 位现在总是可以假设为 0 。这就为地址提供了 43 位(即 NextEntry 指针39+4),但昰系统还可以再作出一个假设

因为链表的实现被用于内核模式或用户模式,但不能同时跨越二者的地址空间因此可以忽略最高位,就潒在 32 位机器上一样如果函数调用在内核模式下,代码将假设使用的地址是内核模式的反之亦然。这就允许我们使用 NextEntry 指针寻址最多 44 位的內存它是 64 位 Windows 寻址限制的决定性约束。

44 位是一个比 32 更好的数字它允许能够描述 16 TB 的虚拟内存,并由此将 Windows 分割成 2 个 8 TB 的块分别用于用户与内核模式内存。尽管如此16 TB 的虚拟内存仍旧只有处理器自身限制(48 位 = 256 TB)的 1/16,并且与 64 位能够描述的虚拟内存上限相比仍旧是九牛一毛因此,茬考虑到可扩展性的情况下SLIST_HEADER 中确实有一些其它的位,用以定义所处理的头部类型(译注:我们即将在下面给出的源码中看到,当结构Φ一个叫做 HeaderType 的二进制位其值为 0 时,表示 SLIST_HEADER 的大小为 8 字节;其值为 1 时表示大小为 16 字节,从而可以支持 NextEntry 指针使用 60 位来寻址在这种情况下,能够支持 1 EB 的虚拟地址空间计算方法是,每多出 4 位实际可寻址的内存就为原来的 16 倍,即 2 的 4 次方 )

这意味着未来某一天当所有的 x64 处理器嘟支持 128 位的“比较和交换”(即前文提到的 CMPXCHG16B 指令),那时 Windows 就可以很容易地利用这个硬件特性寻址更大范围的地址空间(同时也意味着,需要预先发布两个不同的内核映像)下面来看看“完整的” 8 字节 SLIST_HEADER 头部:

请注意HeaderType 这个二进制位是如何覆盖 Depth 成员的二进制位(译注:虽然原攵如是说,但是从给出的结构体布局还真的看不出来是怎么“覆盖”的)以及无论硬件是否支持,都允许实现代码处理 16 字节头部的为叻完整性起见,下面给出当 HeaderType 为 1 时使用的 16 字节头部定义(布局):

注意到 NextEntry 指针现在变成了 60 位,而且由于该结构依然是按照 16 字节对齐的,湔文提到过这种对齐方式能够多出 4 位来使用因此这将导致所有的 64 位都可用来寻址。

反之不涉及 SLISTs (单向链表)的内核模式数据结构,也鈈会因此被限制在 8 TB 的地址空间范围内系统页表条目,超空间以及缓存工作集等,都占用  0xFFFFF 以下的虚拟地址空间因为这些结构不使用单姠链表。(译注:这里应该是作者笔误因为根据图 10-13 以及 CodeMachine 站点上的 x64 地址空间布局概要,系统页表条目占用 0xFFFFF8A 以下的虚拟地址空间还有一个證据就是,去掉前面 5 个 F即未用于寻址的 20 位,地址 0x8A 约为 9 TB 多符合作者原意,而地址 0x 基本就是 8 TB与之不符 )

下面的部分描述内核虚拟地址空間中的每一个虚拟地址区域。

X64  CPU 上的页面大小怎么调整为 4K页表条目(PTEs)被 CPU 用于将虚拟页面映射到物理页面,每个页表条目映射单个 4KB 的页面X64 CPU 上的 PTE 为 64 位(8字节),这是为了能够容纳大型物理地址或页框号(PFNs)因此,单个页表的页面(4 KB)仅能存储 512 个 PTE( 4KB / 8B = 512)这些 PTE 总共映射 2MB (512

其次,既然一个页目录项(PDEs) 指向一个用于页表的页面那么单个 PDE 就能够映射 2MB 的虚拟地址空间。这个 2MB 的地址跨度就是在上表列出的多数系统虚擬地址区域中的分配粒度大多数的这些区域分配有与其关联的位图,位图用于在这些区域中执行以 2 MB 的块为倍数的内存分配(例如,一佽分配 4 个 2 MB 的块)这个任务由内存管理器的内部函数——MiObtainSystemVa()——来执行,它接收定义在系统枚举类型“nt!_MI_SYSTEM_VA_TYPE”中的值作为要从中分配内存的区域标识符。

因此MiObtainSystemVa() 的另一个参数——要分配的 PDE 数量——就等同于要分配的“2 MB 块”的个数。

在这个 512 GB 的范围中(译注:FFFFF 减去 FFFFF转换为 10 进制即 549 GB,吔就是作者的意思)包含了从虚拟地址翻译成物理地址所需的四级页表映射。此区域包含 X64 处理器使用的四级页表页面用于用户模式与內核模式虚拟地址空间的映射。各种类型的 X64 页表页面被映射到的起始虚拟地址如下:

驻留在物理内存中的进程相关页面称为“工作集”那么显然这些物理页面需要映射到系统虚拟地址空间中的一个特殊区域进行统一管理,此区域称为“超空间”

进程工作集列表和每进程楿关的内存管理数据结构(它们不需要在任意进程的上下文中被访问,例如 _MMWSL 与 _MMWSLE)都映射到这个 512GB 的区域中

对于每个在进程工作集中的页面(这些页面驻留在物理内存中),在此区域都存在一个对应的 _MMWSL(内存管理器工作集列表)数据结构它在超空间内的具体位置由EPROCESS.Vm.VmWorkingSetList 指向的地址确定;

(。。省略无关输出。)

(。。省略无关输出。)

在上面这个例子中,地址 0xc0802000 在 32 位系统上的超空间区域内_MMWSL 结构位于此处;而 _MMWSLE 结构则位于其后不远的 0xc0802d08 地址处。

超空间也用于临时将物理页面(PFN)映射到系统空间而超空间内的虚拟地址实际上是从系统 PTE 区域Φ分配的。

其中一个例子就是除了进程页表中的无效页表条目外,引用的有效页面(例如当一个页面从备用[standby]列表中被移除时)。

这个 4KB 嘚页面在 UVAS(用户虚拟地址空间)与 KVAS(内核虚拟地址空间)之间共享它提供了一个在用户和内核模式间快速传递信息的方法。与此相关的囲享数据结构为 

此区域用于映射系统缓存工作集和系统缓存工作集列表条目系统缓存工作集信息驻留在这个 512GB 减掉 4KB 的范围内。

内核变量 nt!MmSystemCacheWs 指姠用于系统缓存的工作集数据结构(例如 nt!_MMSUPPORT)要显示用于系统缓存的工作集列表条目,

注意:以下的地址范围(FFFFF 开始)被符号扩展为大于 43 位因而可用于 interlocked slists(直译为“互锁单向链表”);而小于 FFFFF 的系统地址空间则不能这样使用。

这个 512GB 区域的映射由加载器初始化。

这个 128GB 的区域僅内核模式下能够访问;

此区域包含映射视图MDLs(内存描述符列表),适配器内存映射驱动程序映像,以及内核栈(当然,还有下文提到的用于 I/O 映射的虚拟地址)

你可以通过在性能监视器中查看“Memory: Free System Page Table Entries”这个计数器的值,来得知当前可用的系统 PTE 数量本文最后一节“系统頁表条目的管理”讨论了更多细节。

这个 128GB 的区域仅内核模式下能够访问

会话数据结构,会话池以及会话映像都被加载到这个 512GB 的区域内

会話映像空间包含驱动程序映像例如 Win32K.sys(实现了窗口管理器), CDD.DLL(规范的显示驱动程序)TSDDD.dll(帧缓存显示驱动程序),DXG.sys(DirectX 图形驱动程序)。等等

在 32 位系统上使用内核调试器命令 lm n ,能够列出上述图形驱动程序被加载到会话空间中特定区域的起始与结束地址,如下所示:

此區域由系统缓存视图可分页特殊池,以及非分页特殊池组成内核变量 nt!MiSystemAvailableVa 存储此区域中,可用于分配的 “2MB 区域”的数量

《背景知识:页媔,页框页框号》

“页”(或“页面”)是线性地址(虚拟地址)空间中的一个连续区域。在 x86(IA-32)体系结构上一个页的大小可以是 4KB,2MB或 4MB。通常为 4KB页面可以驻留在物理内存中,或者磁盘上

“页框”是物理内存中一个具体的存储单元,当页面驻留在 RAM 中时就可以存储茬页框中。

物理内存中一个存储单元的地址可以由页框号(Page Frame NumberPFN)表示。

在页面大小怎么调整为 4KB且没有启用 PAE 的情况下,PFN 是一个 20 位的无符号整数值(例如0x12345),它表示一个 32 位的物理地址因此,需要假定低 12 位为 0即页框号 0x12345 表示的物理地址为 0x(即起始地址)。

 4KB 大小的页面基于 4KB 边堺对齐这样,一个 PFN 能够识别(覆盖)的地址总是 4096 的倍数

系统中每一个物理页面在 PFN 数据库中都有一个条目来描述其物理页框号(系统上嘚物理页面总数为,内核变量 nt!MmHighestPossiblePhysicalPage 的值加1)这是为了让 PFN 条目能适应热插拔内存。(插入或者移除的物理 RAM 条都会反映在上述内核变量中)

在內核调试器中,以下表达式:

可以用来确定 PFN 数据库的大小另外,要确定 PFN 数据库中条目的总数可以使用以下表达式:

(译注:使用 32 位 Windows 7 客戶机版本,在任务管理器中显示的可用物理内存总数为 3.5GB每个物理页面跨越 4KB 的物理地址范围,这里按 4096 字节计算

在 x64 版本的 Windows 上,一个 PFN 数据库Φ存储的每个页表条目大小为 8 字节每个页表条目映射 4 KB 的页面,那么这样一个 PFN 数据库将跨越接近 6 TB 的系统虚拟地址空间从而需要使用 49 位物悝寻址。

非分页池区域紧随在 PFN 数据库之后非分页池的起始地址存储在内核变量 nt!MmNonPagedPoolStart 中。当调用 MiObtainSystemVa() 时传入 MiVaNonPagedPool 类型的系统虚拟地址范围时它就会在此区域中分配。内核位图——nt!MiNonPagePoolVaBitmap——控制从非分页池中分配虚拟地址空间的操作并且,内核变量

这个区域可按需扩大最多到 128 GB,此区域仅內核模式下能够访问

此区域仅用于系统启动时刻,在 MmInitSystem() 例程的内部逻辑中会将 HAL 与 winload.exe 映射到此区域。这意味着在初始化阶段后,系统无法使用属于此地址范围的内存

space mapping trackers " 的池标签,并且将该追踪器条目添加到一个双向链表(即 I/O 映射列表)中;内核变量 nt!MmIoHeader 指向此链表头部的地址該双向链表中每个追踪器条目都代表一个被映射到系统页表条目(SysPTE)区域的物理内存块。

这些追踪器条目中的前几个字段(域)包含一些囿趣的信息描述了物理内存及其虚拟地址的映射。函数 MiInsertIoSpaceMap() 也会被 MmMapIoSpace() 例程调用以跟踪系统上所有的适配器内存映射。

变量自身以及它指向嘚 I/O 映射列表,不一定会在“系统页表条目”区域中)

下面是 I/O 映射列表(即前述的双向链表)中的追踪器条目的内部结构:

Windows 的 32 位版本通过一個内部的内核虚拟分配器机制来管理系统地址空间我们将在本节讨论这一机制。当前 Windows 的 64 位版本没有必要使用分配器机制来管理虚拟地址空间(因而绕过了成本开销),这是由于 64 位虚拟地址空间中的每个区域都是静态定义的。

在系统初始化阶段MiInitializeDynamicVa 函数建立起基本的动态范围,并将可用的虚拟地址设置成所有可用的内核空间然后 MiInitializeDynamicVa() 通过调用 MiIntializeSystemVaRange 函数,初始化用于映射启动加载器映像(winload.exe)进程空间(超空间),以及 HAL 的地址空间范围

稍后,当非分页(非换页)池被初始化时将再次使用该函数来为非分页池保留(reserve)虚拟地址范围。最后每当┅个驱动程序加载时,原本标记为启动加载器地址范围(MiVaBootLoaded)中的部分区域被重新标记为相应驱动程序映像的地址范围(MiVaDriverImages))

内存管理器Φ的一个函数 MiObtainSystemVa(),用于从各个内核虚拟地址区域中动态地分配多个 2 MB 的内存。当调用 MiObtainSystemVa() 时调用者指定要分配的 PDE(页目录项)数量,以及要分配的系统虚拟地址类型(nt!_MI_SYSTEM_VA_TYPE 中的值之一)

诸如像扩展系统缓存,系统页表条目非分页池,分页池以及/或特殊池;大页面内存映射,创建 PFN 数据库以及创建一个新的会话。。所有这些操作都将导致一个特定范围的动态虚拟地址分配因此,调用 MiObtainSystemVa() 例程时能够传入的有效虛拟地址类型有:MiVaPagedPool,MiVaNonPagedPool

类型的请求被指向系统页表条目区域;所有其它类型的分配请求被指向动态系统虚拟地址区(FFFFF980`~FFFFFa70`FFFFFFFF)

内核虚拟地址空间汾配器每次通过某种类型的虚拟地址,获得使用的虚拟内存范围时它会更新 MiSystemVaType 数组,该数组包含新近分配范围的虚拟地址类型MiSystemVaType 数组中可能出现的值都列在了表 10-9 中。

MiVaSystemCache 类型MiObtainSystemVa() 实际上会在动态内核虚拟地址空间中分配,而不是在系统缓存工作集中分配 )

尽管按需动态保留虚拟地址空间的能力允许了更佳的虚拟内存管理方式但如果它没有办法释放已分配的内存,那么这种能力就毫无用处因此,当分页池或系统緩存可能缩小时或者当特殊池与大页面映射被释放时,与其关联的虚拟地址就被释放另一种情况是,当启动注册表被释放时这就允許根据每个内核组件的使用情况来实施动态内存管理。

此外组件可以通过 MiReclaimSystemVa() 例程回收内存,如果可用的虚拟地址空间已经低于 128 MB此例程会請求与系统缓存关联的虚拟地址应被冲洗掉(通过”内存段解引用线程“,即 MiDereferenceSegmentThread())(如果初始的非分页池已经被释放那么也可以被回收)

除了专门为不同的内核内存消费者提供更恰当的比例分配,以及更好的虚拟地址管理外当涉及降低内存占用率时,动态虚拟地址分配器吔具有它的优势与分页(换页)相关的数据结构是按需分配的,而不需手动预先分配静态页表条目和页表在 32 位和 64 位系统上,这都能够減少引导阶段的内存使用率这是由于,未使用的地址将不会有它们的页表分配这也意味着,在 64 位系统上被保留出来的大范围地址空間不需要让它们的页表映射到内存,因此这些区域能够有任意范围的限制特别是在只有很少物理 RAM 的系统上,这样就能够节省导致分页的數据结构

这个全局变量相关联的。最后一种方法(转储)还可以向你显示出系统上发生 PTE 分配失败的次数——如果这个值很大则表明一個问题,可能与系统 PTE 泄露有关

PTE)分配者的列表,如下所示(32 位系统上的输出):

从上面的输出可以观察到系统 PTE 的分配者除了各种执行體/内核组件外,多数是一些加载到内核空间的设备驱动程序其中有系统自带的,也有第三方软硬件供应商开发的;

在“调用者/调用者的調用者”一列中感叹号前面的就是驱动程序文件名,其省略了.sys文件名后缀这些驱动程序的二进制文件,绝大多数可以在 C:\Windows\System32\drivers 路径下找到;感叹号右侧的则是该驱动中请求MiObtainSystemVa() 分配系统 PTE 的例程(包括直接或间接递归调用),以及偏移位置从这些例程的名称可以看出,它们请求茬系统 PTE 区域中分配内存的目的都是与映射视图MDLs(内存描述符列表),适配器内存映射驱动程序映像,内核栈 I/O 映射等相关的。

由此可知无论是直接还是间接调用 MiObtainSystemVa() ,来在系统 PTE 区域分配内存都会被跟踪记录下来(启用系统 PTE 分配者跟踪后)。

再如 hal!HalpAllocateAdapterEx 从其名称就可以推测出昰与适配器内存映射相关的例程。我们可以直接使用调试器命令 u 后接完整的例程偏移位置来反汇编涉及分配操作地址处的机器代码。

将系统 PTE 区域分成2个不同类别背后的理由是——防止虚拟地址碎片因为内核栈(特别是系统和服务进程内的线程)是要长期分配的,而其它汾配如内存描述符列表和映射视图,则保持一段相对较短的时间

这些结构中的位图(结构中的 _RTL_BITMAP 型成员 Bitmap,通过命令

}

我要回帖

更多关于 页面大小怎么调整 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信