目录

  • 前言
  • Chapter 4 Paging
    • 4.1 分页模式和控制位
      • 4.1.1 四种分页模式
      • 4.1.2 启用和切换分页模式
      • 4.1.3 分页属性控制
      • 4.1.4 Enumeration of Paging Features by CPUID
    • 4.2 分层页表结构概览
    • 4.4 PAE 分页模式
      • 4.4.1 PDPTE寄存器
      • 4.4.2 线性地址转物理地址
  • 实验题:实现页表浏览工具
    • 0. 查看源码
    • 1. 环境设置
    • 2. MFC浏览工具的代码实现
    • 3. 驱动代码的实现

前言

物理地址扩展 Physical Address Extension(缩写PAE)。
解释:正常情况32位CPU可以存取4G的物理内存,但在现实中,实际情况是内存的发展速度大于CPU的发展速度,所以才有了让32位CPU存取超过4G内存的需求。实现方式就是给CPU增加了4根地址线,达到36根,于是可寻址64G大小的内存。

Intel到目前为止设计了4种分页模式,分别是:32位、PAE、4-level、5-level这四种模式。本文主要讲了Intel是如何设计PAE模式的页表相关数据结构。

  • “Chapter 4 Paging”部分,是笔者在阅读Intel手册时做的翻译笔记,对应原文的 Volume3: Chapter 4 Paging。翻译有不准确的地方,以原文为准。可以在这里下载手册。Intel® 64 and IA-32 Architectures Software Developer Manuals
  • “实验题”部分,实现了一个可以浏览进程页表的小工具,可以在这里查看源码。github源码

Chapter 4 Paging

4.1 分页模式和控制位

分页控制有关的寄存器

  • CR0 标志位:WP(bit 16)、PG(bit 31)
  • CR4 标志位:PSE(bit 4)、PAE(bit 5)、PGE(bit 7)、PCIDE(bit 17)、SMEP(bit 20)、SMAP(bit 21)、PKE(bit 22)、CET(bit 23)、PKS(bit 24)
  • IA32_EFER MSR 标志位:LEM(bit 8)、NXE(bit 11)
  • EFLAGS 标志位:AC(bit 18)

软件(应该指操作系统)如何启用分页功能:确保CR3中是分页结构表的物理内存地址,然后使用MOV指令置CR0.PG位。

4.1.1 四种分页模式

本节内容:根据 CR0.PG、CR4.PAE、CR4.LA57和IA32_EFER.LME,判断是否启用分页,以及是开启的什么分页模式。

CR0.PG = 0 表示未启用分页模式,此时会把线性地址直接当作物理地址使用。

CR0.PG = 1 表示启用分页模式。 Paging can be enabled only if protection is enabled (CR0.PE = 1)。此时由CR4.PAE、CR4.LA57、和IA32_EFER.LME决定启用哪种分页模式。

  • 32-bit paging 模式 CR4.PAE = 0 (详见4.3节)
  • PAE paging 模式 CR4.PAE = 1 and IA32_EFER.LME = 0 (详见4.4节)
  • 4-level paging 模式 CR4.PAE = 1, IA32_EFER.LME = 1, and CR4.LA57 = 0 (4表示4层表寻找Pages页,详见4.5节)
  • 5-level paging 模式 CR4.PAE = 1, IA32_EFER.LME = 1, and CR4.LA57 = 1 (5表示5层表寻找Pages页,详见4.5节)
    32-bit 和PAG模式用于保护模式32位模式,IA32_EFER.LME = 0
    4-level和5-level模式用于64位模式(IA-32e表示64位模式),IA32_EFER.LME = 1

四种模式的区别:

  • 线性地址宽度
  • 物理地址宽度
  • 分页大小:4K、2M、4M、1G
  • 支持execute-disable,数据执行保护
  • 支持PCIDs,操作系统可以启用缓存线性地址的功能,不是很懂,先放放
  • 支持 protection keys,不知道干嘛的

    4-level5-level模式还有两个子模式:
  • 兼容模式:兼容32位的模式
  • 64位模式:虽然是64位线性地址,但是实际上4-level只使用了低48位做线性地址,而5-level页只使用低57位,物理地址线都只有52根。

4.1.2 启用和切换分页模式

本节内容:根据 CR0.PG、CR4.PAE、CR4.LA57和IA32_EFER.LME,如何启用并且切换不同的分页模式
讲解在不同模式之间切换的规则,这部分不感兴趣,略过。

4.1.3 分页属性控制

本节内容:通过CR0.WP、CR4.PSE、CR4.PGE、CR4.PCIDE、CR4.SMEP、CR4.SMAP、CR4.PKE、CR4.CET、CR4.PKS和IA32_EFER.NXE控制在不同分页模式下Pages的属性

  • CR0.WP
    写入数据保护标志位:
    等于0, supervisor-mode(应该指0环应用程序)可以向具有只读属性的页写数据;等于1,则不可以操作。
    这个标志位对User-mode(应该时3环应用程序)没有影响,因为只要是只读属性的页,3环程序都不能写。
    (4.6节有更详细的介绍)

  • CR4.PSE
    是否启用4M分页:
    只对32-bit paging 模式作用,等于0,表示分页大小只能是4K;等于1,可以选择4K或4M分页。其它三种模式的分页大小可以自由选择,不受该位的控制。(4.3节有更详细的介绍)

  • CR4.PGE
    是否启用全局共享页:
    等于0,不同进程间不会共享物理内存;等于1,进程间可以共享物理内存。(可能翻译的不对,帖上原文)
    CR4.PGE enables global pages. If CR4.PGE = 0, no translations are shared across address spaces; if CR4.PGE = 1,
    specified translations may be shared across address spaces.(4.10.2.4节有更详细的介绍)

  • CR4.PCIDE
    启用process-context identifiers,对4-level5-level模式作用。
    PCIDs逻辑处理器缓存多个线性地址。(4.10.1节有更详细的介绍)

  • CR4.SMEP
    If CR4.SMEP = 1, software operating in supervisor mode cannot fetch instructions from linear addresses that are accessible in user mode.(4.6节有更详细的介绍)

  • CR4.SMAP
    If CR4.SMAP = 1, software operating in supervisor mode cannot access data at linear addresses that are accessible in user mode. Software can override this protection by setting EFLAGS.AC.

  • CR4.PKE and CR4.PKS
    4-level和5-level模式将每一个线性地址与保护key相关联。
    CR4.PKE=1时,PKRU寄存器表示,user-mode的线性地址所关联的保护key,是否可读或可写。
    CR4.PKS=1时, the IA32_PKRS MSR does the same for supervisor-mode linear addresses.

  • CR4.CET
    这个好难理解。
    If CR4.CET = 1, certain memory accesses are identified as shadow-stack accesses and certain linear addresses translate to
    shadow-stack pages.

  • IA32_EFER.NXE
    执行保护,对4-level5-level模式作用。如果设为1,则不能执行指令,但是可以读指令。

4.1.4 Enumeration of Paging Features by CPUID

这部分保护标志位的意义和用法。
PSE: page-size extensions for 32-bit paging.
PAE: physical-address extension.
PGE: global-page support.
PAT: page-attribute table.
PSE-36: page-size extensions with 40-bit physical-address extension.
PCID: process-context identifiers.
SMEP: supervisor-mode execution prevention.
SMAP: supervisor-mode access prevention.
PKU: protection keys for user-mode pages.
OSPKE: enabling of protection keys for user-mode pages.
CET: control-flow enforcement technology.
LA57: 57-bit linear addresses and 5-level paging.
PKS: protection keys for supervisor-mode pages.
NX: execute disable.
Page1GB: 1-GByte pages.
LM: IA-32e mode support.
CPUID.80000008H:EAX[7:0] reports the physical-address width supported by the processor.
CPUID.80000008H:EAX[15:8] reports the linear-address width supported by the processor.

4.2 分层页表结构概览

不同模式使用的页表结构是不一样的,有的只是用2张表,有的则更多。
每张表的大小都是4096字节,对于32-bit模式,每一项是4字节,共1024项;对于其它三种模式,每一项是8字节,每张表512项。PAE模式是个特例,它的第一张表只有4项。

不同模式对线性地址的处理是不一样的,详细章节会讲。

这里提出了两个名词:page frame 线性地址中用来寻址的部分;page offset 线性地址中用作偏移的部分。

每一项中的地址部分都是物理内存地址。

第一张表总是保存在CR3寄存器中。

四种模式解析线性地址(4K分页举例):

  • 32-bit模式:32:22(10位)表1下标,21:12(10位)表2下标,11:0(12位)用作分页内的偏移量。
  • PAE模式:31:30(2位)表1下标,29:21(9位)表2下标,20:12(9位)表3下标,11:0(12位)分页内的偏移量。
  • 4-level模式:每张表都是512项,总共4张表,所以47:39、38:30、29:21、20:12对应4张表的下标,11:0(12位)分页内的偏移量。
  • 5-level模式:使用5张表,56:48是第一张表下标,其余的根4-level模式的一样。

总结上面的解析线性地址过程,其实就是查表,查表,再查表。有些情况查表过程可能会中断,比如说遇到缺页异常时。
还有两种特殊的情况:

  • 查表过程中,剩余没有解析的线性地址宽度超过12位,如果当前表项的属性位bit 7(PS位—page size)等于1,当前项就是最后的页
  • 查表过程中,剩余没有解析的线性地址宽度等于12位,bit 7不再是PS位,另有它用,当前项则指向另一个表

对上述的第一种情况举例:
32-bit模式,如果分页大小是4M(CR4.PSE=1),那么表1就是存储的页,总共1024项,1024*4M=4G,正好寻址4G空间,表2就不存在了。再比如,PAE模式下,如果分页大小是2M,查到第2张表就时页了,此时没有了表3。

不同的表结构都有名字,参考下图:

对于上面的缩写,通常我们有下面的叫法:
PTE 页表,存放的每一项是最终的Pages物理地址,32位的分页大小有4K、2M、4M,64位则能扩展到1G大小
PDE 页目录表,存放的每一项是PTE
PDPTE页目录指针表,PAE模式只有4项,4-level和5-level模式都是填满的512项,每一项指向一个页目录表。
PML4E和PML5E暂时也不知道,实际上用法类似,各增加一层表的

4.4 PAE 分页模式

寄存器标志位:
CR0.PG = 1
CR4.PAE = 1
IA32_EFER.LME = 0

4.4.1 PDPTE寄存器

CR3指向 page-directory-pointer表。其中:
4:0 没有用
31:5 存放指向表的物理地址
63:52 没有用

page-dirctory-pointer表中由4个8字节的大小的PDPTEs组成,每个可寻址1-GByte大小的线性地址空间。
对应这4个PDPTE,逻辑处理器内部维护着与之对应的四个non-architectural寄存器,分别是PDPTE0、PDPTE1、PDPTE2、PDPTE3。出现下面几种情况时,逻辑处理器会重新加载内存中的PDPTEs到4个寄存器:

  • 如果使用MOV to CR0或MOV to CR4指令修改了这些寄存器中的标志位(CR0.CD, CR0.NW, CR0.PG, CR4.PAE, CR4.PGE, CR4.PSE, or CR4.SMEP),PDPTESs会从CR3中执行的地址重新加载
  • 在PAE分页模式,如果下执行MOV to CR3指令,PDPTESs会从CR3中执行的地址重新加载
  • 在PAE分页模式,如果CR3中的值被task switch修改,会从新的CR3中加载PDPTEs
    下表中说明了PDPTE的结构:
用途
0(P) Present,等于1表示此项指向一个页目录表,等于0则此项不包含页目录表
2:1 保留位,必须填0
3(PWT) Page-level write-through,用来间接确定访问页目录表所需要的内存属性(详见4.9节)
4(PCD) Page-level cache disable,用来间接确定访问页目录表所需要的内存属性(详见4.9节)
8:5 保留位,必须填0
11:9 忽略
(M-1):12 指向页目录表的4K对齐的物理地址
63:M 保留位,必须填0

注:M表示MAXPHYADDR,最大物理地址宽度,该手册中是52根地址线。

4.4.2 线性地址转物理地址

PAE模式下,可以使用4K或2M分页。
如何确定是4K分页还是2M分页:

  • 线性地址的31:30(2位)用来选择4个PDPTE寄存器中一个,称为PDPTEi,i等于这两位的值。每个PDPTEi可以对应1G大小的线性地址空间。如果PDPTEi的P位是0,那么这一项就是无效的,就是说该项不包含对应的页目录表,同时会产生一个page-fault异常(详见4.7节)。
  • 如果PDPTEi的P位是1,那么其51:12(40位)指向了页目录表的物理地址。每个页目录表由512项8字节的PDEs组成。

意思就是线性地址的前两位用于确定页目录指针表(PDPTE)的下标,找到4个中的一个页目录表。
页目录表,每个页面录表含有512个表项,每个表项8字节大小,指向一个页表或者指向一个2M的页,这要根据下面介绍的PS标志位来确定。

  • 如果PDE’s页目录表项的PS位等于1,说明这一项指向的就是一个最终的2M的分页,物理地址由该项的51:21(31位)和20:0(21位)确定。物理地址线最大52根,有的CPU是36根,那么高位就是35:21(15位),有的CPU有52根的,高位才是51:21。
  • 如果PDE’s页目录表项的PS位等于0,说明这一项指向的是页表。页表的物理地址跟上面的情况一样也分为36根物理地址线和52根物理地址线。

如果是2M分页,那么线性地址后30位中,29:21(9位)用来作为表2(页目录表)的下标索引,来确定最终的页地址;20:0(21位)作为2M页内的偏移量。
如果是4K分页,那么线性地址后30位中,29:21(9位)作为表2(页目录表)的下标索引,20:12(9位)作为表3(页表)的下标索引,11:0(12位)作为4K页内的偏移量。

如果页目录表项(PDE)或者页表项(PTE)的P位(bit 0)等于0,或者置位它们的任意一位保留位,这个表项将会失效,并且会引起page-fault异常(详见4.7节)。

PAE模式中的保留位有下面几个:

  • If the P flag (bit 0) of a PDE or a PTE is 1, bits 62:MAXPHYADDR are reserved.
  • If the P flag and the PS flag (bit 7) of a PDE are both 1, bits 20:13 are reserved.
  • If IA32_EFER.NXE = 0 and the P flag of a PDE or a PTE is 1, the XD flag (bit 63) is reserved
  • If the PAT is not supported:
    — If the P flag of a PTE is 1, bit 7 is reserved.
    — If the P flag and the PS flag of a PDE are both 1, bit 12 is reserved.

下图是4K分页的线性地址转物理地址的过程示意图。

下图是2M分页的线性地址转物理地址的过程示意图。

下图是PDPTE、PDE-2M、PDE-4K、PTE各表项结构的示意图:

手册中给出了PDE-2M、PDE、PTE结构的详细解释,是下面三个表:

首先是PDE-2M表项结构解析:Table 4-9. Format of a PAE Page-Directory Entry that Maps a 2-MByte Page

用途
0(P) Present,必须等于1,表示该项指向一个2M分页
1(R/W) Read/Write,如果为0,不允许向2M的分页写数据
2(U/S) User/supervisor,权限标志位,等于0则3环程序不能访问2M的分页
3(PWT) Page-level write-through,用来间接确定访问2M分页所需要的内存属性
4(PCD) Page-level cache disable,用来间接确定访问2M分页所需要的内存属性
5(A) Accessed,标志这个2M分页是否已经被访问过
6(D) Dirty,标志这个2M分页是否已经被写入过数据
7(PS) Page size,分页大小标志位,必须等于1(否则这项的意义变为指向4K分页的页表)
8(G) Gloabe,如果CR4.PGE等于1,该位用来确定这个页是否是全局共享的页
11:9 Ignored
12(PAT) 如果支持PAT,则用来间接确定访问2M分页所需要的内存属性
20:13 Reserved,保留位,必须是0
(M-1):21 2M分页的物理地址,36根物理线是35:21(15位),有的CPU有52根线的,是51:21
62:M Reserved,保留位,必须是0
63(XD) 如果 IA32_EFER.NXE标志位等于1,则该页中的数据不可执行(从该页中获取指令将被禁止); IA32_EFER.NXE等于0,该位位保留位,必须填0

PDE表项结构解析:Table 4-10. Format of a PAE Page-Directory Entry that References a Page Table

用途
0(P) Present,必须等于1,表示该项指向一个页表
1(R/W) Read/Write,如果为0,不允许向其包含的1024个页(共2M)写数据
2(U/S) User/supervisor,权限标志位,等于0则3环程序不能访问其包含的1024个页(共2M)
3(PWT) Page-level write-through,用来间接确定访问页表所需要的内存属性
4(PCD) Page-level cache disable,用来间接确定访问页表所需要的内存属性
5(A) Accessed,标志这个表项已经被访问了(被线性地址翻译器访问了)
6(D) Ignored
7(PS) Page size,分页大小标志位,必须等于0
11:8 Ignored
(M-1):12 页表的物理地址,36根物理线的CPU是25:12(24位),有的CPU有52根线的,是51:12(40位)
62:M Reserved,保留位,必须是0
63(XD) 如果 IA32_EFER.NXE标志位等于1,则该项指向的页表中的所有页(1024个页)中的数据不可执行; IA32_EFER.NXE等于0,该位位保留位,必须填0

PTE表项结构解析:Table 4-11. Format of a PAE Page-Table Entry that Maps a 4-KByte Page

用途
0(P) Present,必须等于1,表示该项指向一个4K分页
1(R/W) Read/Write,如果为0,不允许向4K的分页写数据
2(U/S) User/supervisor,权限标志位,等于0则3环程序不能访问4K的分页
3(PWT) Page-level write-through,用来间接确定访问4K分页所需要的内存属性
4(PCD) Page-level cache disable,用来间接确定访问4K分页所需要的内存属性
5(A) Accessed,标志这个4K分页是否已经被访问过
6(D) Dirty,标志这个4K分页是否已经被写入过数据
7(PAT) 如果支持PAT,则用来间接确定访问4K分页所需要的内存属性
8(G) Gloabe,如果CR4.PGE等于1,该位用来确定这个页是否是全局共享的页
11:9 Ignored
(M-1):12 4K分页的物理地址,36根物理线的CPU是25:12(24位),有的CPU有52根线的,是51:12(40位)
62:M Reserved,保留位,必须是0
63(XD) 如果 IA32_EFER.NXE标志位等于1,则该页中的数据不可执行(从该页中获取指令将被禁止); IA32_EFER.NXE等于0,该位位保留位,必须填0

实验题:实现页表浏览工具

0. 查看源码

github源码

1. 环境设置

测试操作系统:winxp sp3

开发环境配置:
VS2015 实现MFC对话框工程
WDK 7.1.0开发winxp驱动

如何启用PAE模式?
读者可以检索关键字“winxp pae”,会搜索到很多关于winxp系统启用PAE模式的教程。

2. MFC浏览工具的代码实现

工具的使用效果如下图:

第一栏,显示系统中的所有进程,通过调用CreateToolhelp32Snapshot 实现遍历进程。
第二栏,展示页目录指针表的表项(PDPTE),选中上级目录的某个进程后,MFC程序调用驱动程序接口,加载该进程的PDPTE,最后展示有效表项。
第三栏,展示页目录表的表项(PDE),选中上级目录的某个PDPTE表项后,与上述类似流程。
第四栏,展示页表项(PTE),流程与上述类似。

关于加载进程页表速度慢的问题:
对于PAE模式,进程的页表项数量总共有:4 PDPTE x 512 PDE x 512 PTE
在最初版本的工具设计中,使用3层循环来遍历页表项,一次性加载某个进程的所有页表。但是出现加载速度慢的问题。所以改进了加载方式,变成根据索引加载一个PDPTE表项下的512项PDE,或者加载一个PDE表项下的512个PTE,这样改进之后,加载速度明显改善。

代码:定义保存页表数据的结构体

namespace PAEPaging
{struct PDE_T{PDE val;PTE PTEs[512];BOOL LoadedFlag;};struct PDPTE_T{PDPTE val;PDE_T PDEs[512];BOOL LoadedFlag;};struct PDPTE_TT{ULONG cr3Val;PDPTE_T PDPTEs[4];};
}

代码:调用驱动接口,加载页表的实现

BOOL COperateKernel::LoadPages(DWORD dwPID, __in DWORD dwPDPTEIdx, __in DWORD dwPDEIdx, PAEPaging::PDPTE_TT* tt)
{...if (DeviceIoControl(hFile, IOCTL_GET_PAGES_PAE, inBuff, sizeof(inBuff), outBuff, sizeof(outBuff),&dwBytesRead, NULL)){DWORD dwOutBuffOffset = 0;// 加载 PDPTE 表if (dwPDPTEIdx == -1 && dwPDEIdx == -1){for (int i = 0; i < 4; i++){PAEPaging::PDPTE *pPDPTE = (PAEPaging::PDPTE*)((DWORD)outBuff + dwOutBuffOffset);tt->PDPTEs[i].val = *pPDPTE;dwOutBuffOffset += sizeof(PAEPaging::PDPTE);}}// 加载 PDE 表else if (dwPDPTEIdx != -1 && dwPDEIdx == -1){for (int i = 0; i < 512; i++){PAEPaging::PDE *pPDE = (PAEPaging::PDE*)((DWORD)outBuff + dwOutBuffOffset);tt->PDPTEs[dwPDPTEIdx].PDEs[i].val.uint64 = pPDE->uint64;dwOutBuffOffset += sizeof(PAEPaging::PDE);}}// 加载 PTE 表else if (dwPDPTEIdx != -1 && dwPDEIdx != -1){for (int i = 0; i < 512; i++){PAEPaging::PTE *pPTE = (PAEPaging::PTE*)((DWORD)outBuff + dwOutBuffOffset);tt->PDPTEs[dwPDPTEIdx].PDEs[dwPDEIdx].PTEs[i] = *pPTE;dwOutBuffOffset += sizeof(PAEPaging::PTE);}}bRet = TRUE;}...
}

3. 驱动代码的实现

NTSTATUS GetProcessPages(PVOID pInBuff, PVOID pOutBuff, ULONG nOutLength, ULONG* nBytes)
{...// 加载 PDPTE 表if (nPDPTEIdx == -1 && nPDEIdx == -1){for (int i = 0; i < 4; i++){ULONG64 paPDPTE = paCR3 + 8 * i;ULONG64 PDPTE = GetQuadByPA(paPDPTE);*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PDPTE;nWriteOffset += sizeof(ULONG64);}}// 加载 PDE 表else if (nPDPTEIdx != -1 && nPDEIdx == -1){ULONG64 paPDPTE = paCR3 + 8 * nPDPTEIdx;ULONG64 PDPTE = GetQuadByPA(paPDPTE) & 0xFFFFFF000;for (int i = 0; i < 512; i++){ULONG64 paPDE = PDPTE + 8 * i;ULONG64 PDE = GetQuadByPA(paPDE);*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PDE;nWriteOffset += sizeof(ULONG64);}}// 加载 PTE 表else if (nPDPTEIdx != -1 && nPDEIdx != -1){ULONG64 paPDPTE = paCR3 + 8 * nPDPTEIdx;ULONG64 PDPTE = GetQuadByPA(paPDPTE) & 0xFFFFFF000;ULONG64 paPDE = PDPTE + 8 * nPDEIdx;ULONG64 PDE = GetQuadByPA(paPDE) & 0xFFFFFF000;for (int i = 0; i < 512; i++){ULONG64 paPTE = PDE + 8 * i;ULONG64 PTE = GetQuadByPA(paPTE);*(ULONG64*)((ULONG)pOutBuff + nWriteOffset) = PTE;nWriteOffset += sizeof(ULONG64);}}...
}

WIndows内核学习笔记:分页机制——PAE分页模式相关推荐

  1. Windows x64内核学习笔记(二)—— IA-32e模式

    Windows x64内核学习笔记(二)-- IA-32e模式 IA-32e模式 模式检测 强制平坦段 任务切换 中断门描述符 FS / GS 模式切换 32位程序进内核 64位程序进内核 实验:模式 ...

  2. Linux内核学习笔记 - RCU机制总结

    目录 一.什么是RCU机制 1.历史背景 -- 原始的RCU思想 2.基础架构 -- RCU算法设计 3.实现思路-- 读写回收实现思路 4.实现思路 -- 实例说明 宽限期 订阅--发布机制 数据读 ...

  3. Windows x64内核学习笔记(四)—— 9-9-9-9-12分页

    Windows x64内核学习笔记(四)-- 9-9-9-9-12分页 前言 9-9-9-9-12分页 实验一:线性地址转物理地址 页表基址 定位基址 PTE to PXE 实验二:通过页表基址定位各 ...

  4. 【OS学习笔记】三十三 保护模式九:分页机制对应的汇编代码之---用户程序代码

    本片文章是以下两篇文章: [OS学习笔记]三十 保护模式九:段页式内存管理机制概述 [OS学习笔记]三十一 保护模式九:页目录.页表和页三者的关系详解 对应的用户程序汇编代码. ;代码清单16-2;文 ...

  5. Windows x64内核学习笔记(五)—— KPTI(未完待续)

    Windows x64内核学习笔记(五)-- KPTI(未完待续) KPTI 实验一:构造IDT后门并读取Cr3 参考资料 KPTI 描述:KPTI(Kernel page-table isolati ...

  6. Windows x64内核学习笔记(三)—— SMEP SMAP

    Windows x64内核学习笔记(三)-- SMEP & SMAP SMEP & SMAP 实验:构造IDT后门 第一步:编译以下代码 第二步:构造IDT后门 第三步:运行程序 第四 ...

  7. Windows x64内核学习笔记(一)—— 环境与配置

    Windows x64内核学习笔记(一)-- 环境与配置 前言 新特性 基础要求 实验环境 Guest Win10配置 问题解决 参考资料 前言 之前,跟着海哥学习了windows内核的一些机制,包括 ...

  8. Windows异常学习笔记(二)—— 内核异常处理流程用户异常的分发

    Windows异常学习笔记(二)-- 内核异常处理流程&用户异常分发 用户层与内核层异常 内核异常 分析 KiDispatchException 分析 RtlDispatchException ...

  9. 《寒江独钓》内核学习笔记

    <寒江独钓>内核学习笔记(1)-- IRP - .Little Hann 时间 2013-11-30 15:40:00  博客园_.Little Hann原文  http://www.cn ...

最新文章

  1. 每秒改变一次背景颜色以及由此引发的一些有趣的小事情(.net方向)
  2. 遇到问题:push的时候出现fatal: Authentication failed for
  3. 从马克思哲学客观原理角度——反思大学生创业2017-12-15
  4. Codeforces 1065 E. Side Transmutations
  5. strcpy ,strncpy ,strlcpy地用法
  6. 优化基于ExtJS 4.1的应用
  7. 按顺序插入图片_MysqlInnodb特性之插入缓存
  8. JAVA :RESTLET开发实例(一)基于JAX-RS的REST服务
  9. Java使用swagger时显示实体类注解问题
  10. AI+大数据顶级技术盛会倒计时10天,6.6折票限时特惠!
  11. java关闭通道_调用map方法后,Java 7文件通道未正确关闭
  12. MATLAB中ones()函数的用法
  13. Codeforces 208A:Dubstep(字符串)
  14. Win7系统屏保也可以当桌面壁纸
  15. android emoji 开源库,Emoji开源库推荐_支持emoji表情的js的开源项目总汇
  16. 蛋白组+代谢组联合分析
  17. 针对OpenSSL吐嘈的吐嘈-如此唱反调
  18. Java 获取Word批注所标记的文本和图片
  19. VSCode入门(一)怎样新建项目
  20. 艾永亮:盘点产品创新的三种颠覆方式

热门文章

  1. 计算机怎么进入用户模式,Win7系统怎么进入电脑安全模式?
  2. MISO和MOSI是什么意思
  3. 论开学第三个月干了点啥
  4. cs231n课程资料Python Numpy Tutorial的Python3版本
  5. mongodb针对查询数据保留两位小数或者自定义
  6. 使用JME3开发的Android 3D游戏 - 落樱之剑v2.2
  7. CS143 6、7. 自顶向下和自底向上的语法分析
  8. 使用Auto.js庖丁对Pro Snapshot快照加密的解密打包教程
  9. B/S模式下的MVC架构迭代(2)
  10. 软件项目管理案例教程-韩万江-期末复习