精华内容
下载资源
问答
  • 基于存储过程+分页控件+分页类的无敌分页模式
  • 内存分页之PAE分页模式

    千次阅读 2016-02-25 21:11:14
    PAE分页模式可以将32位的线性地址空间映射到52位的物理地址空间。相比于32位分页方式,其物理地址空间增加到了4PB。但对于在处理器上运行的任一进程而言,其最大的线性地址空间仍然是4GB。页面大小PAE分页主要支持两...

    PAE分页模式可以将32位的线性地址空间映射到52位的物理地址空间。相比于32位分页方式,其物理地址空间增加到了4PB。但对于在处理器上运行的任一进程而言,其最大的线性地址空间仍然是4GB。

    页面大小

    PAE分页主要支持两种页面大小:

    • 4KB页面
    • 2MB页面

    对于4KB页面,其线性地址转换方式如下:
    4KB

    对于2MB的页面,其线性地址转换方式如下:
    2MB

    如何映射(4GB->4PB)

    相比于32位分页方式,PAE的4KB分页要多一级分页,由上图可以看出,多出了PDPT。即Page-Directory-Page-Table。这个Table只有4个入口,因为它只占了两个bit。
    那么它是如何把地址扩展到52位的呢?注意PDPT的表项长度,它有40个bit,再住下的每一级目录都有40个bit,最后加上offset的12个bit, 一共刚好组成了52个bit。但是其线性地址的长度任然是32个bit。所以线性地址空间的大小不变。
    那么现在问题来了?线性地址空间只有4GB,一定不能做到对4PB的物理空间的1:1映射。难道要1对多映射么?怎么映射呢?
    刚开始这个问题让我困惑了很久,线性空间只有4GB,如果不是1对多映射,就算是物理地址有52 bits。也只能用于其中的4GB啊,剩下的只能白白浪费掉!!!
    网上苦苦搜索,没有找到答案,只好再细读IA32 spec。当看到以下几句话的时候才明白过来:
    IA32
    什么意思呢?
    第一句话是讲,PDPT的物理地址被存放在CR3中。也就是说改变CR3, PDPTE也会跟着变。
    第二句话最关键,如果PAE分页被使用,而进程在运行的过程中改变了CR3的值,PDPTE将会指向CR3所保存的新地址。
    这就意味着,我们在内存中不只保存了一套页表,而是保存了多套,进程跟据需要,改变CR3的值,从而实现对当前4GB物理地址之外的访问。这也就说明了一对多是如何实现的。

    展开全文
  • 1.支持设计时支持和两种分页模式,其中综合分页模式的效果如下: 普通分页模式的效果如下: 2.完善的设计时支持,包括自动套用格式和设计时面板设置:   使用方法: 在aspx页面中: 代码如下: <%@ Page...
  • 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)、...

    前言

    物理地址扩展 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分页的线性地址转物理地址的过程示意图。
    4K分页的地址转换

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

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

    手册中给出了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:9Ignored
    12(PAT)如果支持PAT,则用来间接确定访问2M分页所需要的内存属性
    20:13Reserved,保留位,必须是0
    (M-1):212M分页的物理地址,36根物理线是35:21(15位),有的CPU有52根线的,是51:21
    62:MReserved,保留位,必须是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:8Ignored
    (M-1):12页表的物理地址,36根物理线的CPU是25:12(24位),有的CPU有52根线的,是51:12(40位)
    62:MReserved,保留位,必须是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:9Ignored
    (M-1):124K分页的物理地址,36根物理线的CPU是25:12(24位),有的CPU有52根线的,是51:12(40位)
    62:MReserved,保留位,必须是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),流程与上述类似。
    GetPages工具

    关于加载进程页表速度慢的问题:
    对于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);
            }
        }
        ...
    }
    
    
    展开全文
  • 本文基于intel手册,介绍内存虚拟化的硬件基础,分页模式

    • 内存分页是将线形地址转化成物理地址的过程,如果把分页过程看做一个函数,其输入为线形地址,输出为物理地址。不同的分页模式对应不同的函数表达式,有不同的实现。X86有三种分页模式,分别是:32-bit,PAE,4-level。三种分页模式由三个寄存器的标记位控制,分别是CR0.PG,CR4.PAE,IA32_EFER.LME。三种模式都是在保护模式(CR0.PE)开启的情况下所设置的模式。分页模式中页的大小可设置,不同大小的页需要不同位宽的地址来索引,本节默认页大小4K,因此索引该页内的所有内容需要12bit位宽的地址。
    • 不同的分页模式其寻址能力有所不同,这取决于页表项设计,页表项中存放的物理地址位宽决定了寻址能力。三种分页模式下页表项中存放的物理地址位宽各有不同,32-bit分页模式页表项物理地址位宽为32位,因此物理地址的寻址能力为4G;PAE分页模式页表项物理地址位宽最大可配置为52位,因此寻址能力为4P;4-leve分页模式和PAE分页模式相同,页表项物理地址位宽最大可配置位52位,寻址能力为4P。

    思维导图

    在这里插入图片描述

    32-bit模式

    • 32-bit分页模式是分页开启后的默认模式,CR0.PG被置位后默认进入32-bit的分页模式。该模式下只支持32位的线性地址作为输入,并将其转化为32位的物理地址。任意时刻只有4G的线性空间可以被访问。

    层级结构

    • 32-bit分页模式通过三级索引实现线性地址到物理地址的映射,如下图:
      在这里插入图片描述
      32-bit分页模式下,CR3存放的是页目录的物理地址,地址转换时首先通过CR3查找到页目录,再从页目录中查找页表的物理地址,最后从页表中查找目标页面的物理地址。线性地址转换时定位页表项的过程为CR3 -> PDE -> PTE -> Page Physical Address

    PTE/PDE

    • 线性地址低12位的最大寻址能力是4K,通过它可以从一个页面内找到任意地址的内存;中间10位用来在一个拥有2^10=1024个条目的页表中查询目标项,由于页表存放的单位也是页,因此一个页面如果作为页表,其每个条目的长度是4K / 1024 = 4Byte = 32bit。页表项PTE(Page Table Entry)的格式如下:
      在这里插入图片描述
    • 因为PTE指向的是物理页的地址,物理页总是4K(或者大于4K)对齐的,所以物理页地址的低12位总是为0。因此PTE不需要将低12位记录下来,而是利用这12位做其它事情,比如描述所映射的物理页,Intel就是这么设计的,PTE的低12位存放描述物理页的元数据。这些信息包括物理页是否被分配(bit0 = Present),页是否可写(bit1 = R/W),用户特权级是否可以访问此页(bit2 = U/S),页cache是否打开(bit4 = PCD),是否为脏页(bit6 = Dirty),用户程序是否具有对该页的访问权限等。
    • 线性地址的高10位用来在一个拥有2^10 = 1024个条目的页目录中查询目标项,页目录的的每一项存放的是页表地址,页目录的存放单位也是页,一个页面如果作为页目录,其每个条目的长度是4K/1024 = 4Byte = 32bit。页目录项PDE(Page Directory Entry)的格式如下:
      在这里插入图片描述
    • 同PTE类似,PDE由于存放的也是4K对齐的页地址,因此其低12位始终为0,同样可以被复用,PDE的低12位用来存放描述一张页表覆盖的地址空间的元数据。由于PTE描述的是4K页面,一张页表1024个PTE,因此PDE描述1024个4K页面,PDE描述了4MB的物理地址空间。

    CR3

    • 32-bit分页模式下CR3存放的页目录表物理地址,格式如下:
      在这里插入图片描述

    PAE模式

    • PAE(Physical Adress Extend)即物理地址扩展。顾名思义,它是对物理地址的扩展,扩展什么呢?扩展32-bit模式下只能寻址4G内存空间的限制,它可以将32位的线性地址转化位最高52位的物理地址,可以寻址大于4G的地址空间。怎么做到的?PAE分页模式的页表结构变了,页表项长度增加变成了8字节(64bit)。
    • PAE模式的开启需要CR0.PG和CR4.PAE两个标志位同时打开。

    层级结构

    • PAE分页模式下存放页目录物理地址的寄存器不再是CR3,而是该模式下特有4个PDPTE寄存器,4个寄存器从PDPT(page-directory-pointer table)中加载值,该表的物理地址存放到了CR3中。在PAE模式下,只要CR3的值有改变,就会同步更新4个PDPTE寄存器,当发生地址转换时CPU可以直接从PDPTE寄存其中读取页目录的物理地址,4个PDPTE寄存器在地址转换中起到的作用和32-bit模式下CR3的作用相同。
      在这里插入图片描述
      对比32-bit分页模式,PAE分页模式多了一级索引,物理地址转换过程变为CR3 -> PDPTE -> PDE -> PTE -> Page Physical Address。这里要注意,CR3 -> PDPTE的过程并非发生在地址转换流程中,而是在CR3寄存器变化的时候。所以从地址转换效率上说,32-bit模式和PAE模式都只有三次查询动作,效率接近。PAE模式通过多维护4个PDPTE寄存器实现了物理地址的扩展。

    PTE/PDE

    • PAE模式页大小我们也分析4K的情况,同32-bit模式一样,通过低12位可以从一个页面内找到任意地址的内存。因此线性低12位用作查找页面内的偏移。
    • 线性地址的12 ~ 20位,这9位用来在页表中索引目标页表项,9位地址可以索引2 ^ 9 = 512个条目,如果一张页表只存放512个条目,那么每个条目的长度为 2 ^ 12 / 2 ^ 9 = 2 ^ 3 = 8byte = 64bit。有足够的宽度来存放物理地址,而32-bit模式下,最多只有32bit来存放物理地址,这是PAE能够扩展物理地址寻址能力的关键。PTE格式如下:
      在这里插入图片描述
      PTE的低12位仍然用于描述内存页的元数据,剩下的52bit中除最高位以外,其余可以全部用作存放页的物理地址。因此PTE模式下的页表,理论上可以存放51bit的物理地址。Intel在具体实现上,页表中页的物理地址取决于最大物理地址位宽MAXPHYADDR,该值是cpu所支持的最大地址宽度。很明显32-bit分页模式下,MAXPHYADDR为32,PAE分页模式下通常可以配置的值为36,40,52这三个,PTE中存放页面物理地址的区间可以表示为12 ~ MAXPHYADDR
    • 线性地址的21 ~ 29位,这9位用来在页目录表中索引目标页目录表项,9位地址可以索引 2 ^ 9 = 512个条目,同PTE类似,PDE存放的是PTE的物理地址,这个物理地址也是4K对齐,存放页表物理地址的区间可以表示为12 ~ MAXPHYADDR,PDE格式如下:
      在这里插入图片描述

    PDPTE

    • PAE模式下线性地址的最高两位用于索引4个PDPTE寄存器,每个PDPTE(page-directory-pointer table entry)寄存器都存放了一个页目录表的地址,指向一张页目录表。PDPTE寄存器的初始值来自于页目录指针表(page-directory-pointer table),在PAE模式开启之前,用户软件就需要在内存中准备这样一张表,然后将其地址取出,存放到CR3寄存器中。存放的MOV指令会触发加载动作,将内存中表的内容加载到寄存器中。这样PDPTE寄存器就替代了CR3的作用,CPU每次进行地址转换时,不再通过CR3寻找页目录表的地址,而是通过PDPTE寄存器寻找地址。而PDPTE有4个,用哪个呢?它的索引就是线性地址的最高两位。PDPTE格式如下:
      在这里插入图片描述
      PDPTE的格式和PDE/PTE的格式类似,低12位都用于存放描述内存区域的元数据,12 ~ MAXPHYADDR用于存放页目录表的物理地址。

    CR3

    • PAE模式下CR3存放的不再是页目录表的物理地址,而是页目录指针表的物理地址,格式如下:
      在这里插入图片描述
      由于PDPT包含4个PDPTE,所以总长度是4 * 8 = 32字节,PDPT的物理地址32字节对齐,低5位始终为0。CR3寄存器的低5位可以复用,但这里暂时没有定义,因此忽略低5位。除去低5位,CR3的剩余27用于存放页目录指针表的物理地址。

    4-level模式

    • 4-level模式,顾名思义,地址转换需要通过4级层层索引才能实现。4-level与32-bit和PAE相比,最大的不同就是它在地址转换时多了一级,32-bit和PAE可以看做是2-level的地址转换(因为内存里面存放了两张表)。4-level将48位线性地址转化成52位物理地址,因此4-level分页模式必须在64位cpu上才能支持。
    • 4-level分页模式多出的一级索引叫做PML4(Page Map Level 4),它存放的是页目录指针表的地址,4-level模式下的地址转换过程CR3 -> PML4E -> PDPTE -> PDE -> PTE
    • 4-level模式开启需要CR0.PG,CR4.PAE和IA32_EFER.LME三个标志位同时打开。

    层级结构

    • 4-level分页模式增加了PML4结构,层级结构如下:
      在这里插入图片描述

    PTE/PDE

    • 4-level模式下的线性地址,页面大小仍然以4K为例,低12位用作一个物理页面的内部地址索引,线性地址余下的部分被分成了4部分,每个部分都占用9位,用做对应表的索引,可以计算出,每个部分对应的表条目都是2 ^ 9 = 512个,如果页面是4K,那么每个条目的长度为2 ^ 12 / 2 ^ 9 = 2 ^ 3 = 8字节,每个条目都是64bit。
    • 线性地址中用来索引PTE/PDE的域都是9位,格式如下:
      在这里插入图片描述

    PDPTE

    • 4-level分页模式下,页目录指针表被存放到了内存中,其内容并没有加载到4个寄存器上,这一点和PAE模式不同,线性地址中同样用9位来索引PDPTE,其格式如下:
      在这里插入图片描述

    PML4E

    • PML4E(page map level 4 entry)是4-level下新设计的索引表的条目,线性地址的高9位用于索引PML4E,格式如下:
      在这里插入图片描述

    CR3

    • 4-level分页模式下CR3存放的是PML4表的物理地址:
      在这里插入图片描述

    总结

    • 32-bit分页模式和PAE分页模式的线性地址都为32位,4-level分页模式的线性地址为64位,但只用了其中的48位。32-bit分页模式下内存中存放的地址转换表有两张,1张是页目录表,1张是页表;PAE分页模式下内存中存放的地址转换表虽然有3张(Page Directory Pointer Table,Page Directory Table,Page Table),但Page Directory Pointer Table的值会被加载到寄存器中,因此地址转换时也只用了两张表;4-level分页模式下有4张表用于地址转换,分别是PML4 Table,Page Directory Pointer Table,Page Directory,Page Table。
      在这里插入图片描述
    展开全文
  • jsp+javabean+servlet相结合的分页模式,是个很好的分页典型例子!
  • 2套分页模式留言板11-19 还会继续更新,学习是个循序渐进的过程
  • ViewPage各种分页模式

    2013-04-24 15:50:16
    ViewPager提供各种分页,封装好了的库,非常棒的例子,做android开发肯定能用的上。
  • pagination分页组件-带有背景色的分页模式: https://element.eleme.cn/#/zh-CN/component/pagination 结构:src/views/fans/index.vue中的div盒子里 {{item.name}} +关注 //拿到分页组件,看需要哪些数据...
  • 分页模式 分页模式然后先来依次说明下原理: 分页模式:看着和下拉刷新上拉加载的时候像不像?没错,博主这里用的MJRefresh写的效果,往上时下拉改变底部scrollView的偏移量,往下时加载结束改变底部...

    简略效果图

    上面的效果是商品详情页常用的两种模式,分页和不分页。首先请忽略博主懒得去写界面,真正的效果见下面:

    不分页模式
    不分页模式

    这里写图片描述
    分页模式

    然后先来依次说明下原理:
    分页模式:看着和下拉刷新上拉加载的时候像不像?没错,博主这里用的MJRefresh写的效果,往上时下拉改变底部scrollView的偏移量,往下时加载结束改变底部scrollView的偏移量。其他的布局按照正常的界面来即可,so easy。

    不分页模式:这里要着重说明,实现的方式有两种:
    1)把网页放在tableView的cell里,等到网页加载结束后在代理里面获取网页size的height,然后给cell的行高赋值,刷新tableView对应webView的cell(貌似挺麻烦的,不过相对博主使用的方法可能真的好点,为什么好点,看下面);
    2)类似于给webView加header,然后把tableView加入webView的header,方法:

    #pragma mark - creatWebViewForGoodsdetail
    - (void)creatWebViewForGoodsdetail
    {
        detailWebView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 64, 375, 667 - 64)];
        detailWebView.backgroundColor = [UIColor whiteColor];
            //在webView的scrollView中插入一块和tableViewsize的height一样的区域(实则是改变偏移量)
        detailWebView.scrollView.contentInset = UIEdgeInsetsMake(detailTableView.contentSize.height, 0, 0, 0);
        //插入这块区域后,那块区域是黑色的,看起来视觉真。。。好吧,就是丑,所以设置下面两句代码即可
        detailWebView.backgroundColor = [UIColor clearColor];
        detailWebView.opaque = NO;
    
        [self.view addSubview:detailWebView];
    
        /*然后tableView的frame一开始固定了,但是如果tableView可滚动高度大于或者小于其实际frame
        的高度岂不是能相对于web滚动,这肯定不合适,所以这里重新设置tbaleView的frame的高度为
        tableView可滚动的高度*/
        detailTableView.frame = CGRectMake(0, -detailTableView.contentSize.height,375, detailTableView.contentSize.height);
        [detailWebView.scrollView addSubview:detailTableView];
    
    
    
        NSURLRequest *webRequest = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"http:www.baidu.com"]];
        NSURLResponse *response = nil;
        [NSURLConnection sendSynchronousRequest:webRequest returningResponse:&response error:nil];
        [detailWebView loadRequest:webRequest];
    
    }
    

    因为是tableView加在web上,所以当web加载完毕时tableView才会显示出来,第一次进入网速慢的话可能会显示空白,会有点慢,算是一个弊端吧,不过一般来说没人会注意,但这的确是一个小问题,所以能分页最好分页。或者把web放在cell中来做。

    代码下载地址:点击前往下载

    展开全文
  • 分页系他人书写,本人修改! 附带详细使用方法 以及函数说明!可直接用于php项目 !支持多种分页方式!
  • 转载自:老二牛车教育 » 【产品设计】瀑布流与分页模式比较 在设计资料量比较大的网站或是应用程式时,我们常常会遇到的问题是要采用分页(Pagination),还是移动卷轴(Scrolling)便自动载入、呈现资料。 ...
  • SQL Server 2005下分页的四种模式,生成的存储过程脚本
  • 分页,即时搜索和排序 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation 各式各样的扩展: Editor, TableTools, FixedColu...
  • 使用方法: --------参数获取部分------------------- ...-------分页显示------------------- $subPages=new SubPages($page_size,$page_nums,$pageCurrent,$sub_pages,"?page=",2); 就这么简单
  • (翻译)分页模式(Pagination)

    千次阅读 2018-06-02 17:07:10
    问题概述   用户要查看数据集合的部分内容,且数据集合以可理解的方式进行排列。 用途   用于不适合在一个页面/屏幕中显示所有数据时;...  如果不想在切换到下一页内容时暂停用户动作,不要使用本模式
  • 用于中继兼容模式的GraphQl光标SQL分页助手 :purple_heart: :blue_heart: :purple_heart: 库巴·斯维拉(Kuba Svehla)的《用爱制造》 :purple_heart: :blue_heart: :purple_heart: 动机 这个库是很棒的的扩展,它...
  • iViewUI普通版的表格排序貌似只支持对表格已有内容的排序,所以对分页后的表格数据支持不好,而且表格条目的index在排序后不会重新自动修改,导致看起来界面比较凌乱 解决方法 我想到的方法比较直接,就是在外面把...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,397
精华内容 55,358
关键字:

分页模式