页表项(PTE)地址计算公式的解释

本文深入解读了Windows内核中计算PTE地址的公式,并通过简化和修正公式,清晰阐述了其背后的原理。文章还对比了不同情况下的公式应用,为理解和实现分页机制提供详细指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自: http://www.pediy.com/kssd/pediy10/62497.html


《JIURL玩玩Win2k内存篇 分页机制 (三)》中提到计算虚拟地址对应PTE地址的公式,如下:


代码:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
从虚拟地址转换到物理地址的过程来看,计算PTE需要虚拟地址的高10位做页目录索引,还需要第12 - 21位做页表索引,上面的公式晃眼看起来,貌似是错的,但是偏偏它又是对的,为什么捏?
其实很简单,因为1024个页表被映射在0xC0000000 - 0xC03FFFFF地址中,暂且不理会页目录被映射到哪,只要知道页目录里的1024个页目录项分别指向0xC0000000 - 0xC03FFFFF地址中的1024个页表就行了(其实这是因为页目录和一个页表完全重合的原因,见 《JIURL玩玩Win2k内存篇 分页机制 (四)》),这样就可以得到一个关系,页目录索引n指向的页表就等于0xC0000000 + n * 页表大小,一个页表的大小是1024 * 4  = 4096 = 2的12次方,得到了页表,在加上页表索引就可以得到页表项(PTE)的地址了,用公式表示就是如下:

代码:
//为了缩短表达式,用VA表示虚拟地址
//           页目录索引                  页表索引
PTE_Addr=((VA&0xffc00000)>>22)*4096+((VA&0x3ff000)>>12)*4+0xc0000000
        =(((VA&0xffc00000)>>22)<<12)+(((VA&0x3ff000)>>12)<<2)+0xc0000000
        =((VA&0xffc00000)>>10)+((VA&0x3ff000)>>10)+0xc0000000
        =((VA&0xffc00000)+(VA&0x3ff000)>>10)+0xc0000000
        =((VA&(0xffc00000|0x3ff000))>>10)+0xc0000000
        =((VA&0xfffff000)>>10)+0xc0000000
        =(((VA&0xfffff000)>>12)<<2)+0xc0000000
        =((VA&0xfffff000)>>12)*4+0xc0000000
由于VA的低位被清零,所以上面的移位操作化简是成立的。最后的一个表达式已经很明显了,VA & 0xfffff000完全是多余的,因为始终要>>12,所以最终公式就是:

代码:
PTE_Addr = (VirtualAddr >> 12) * 4 + 0xC0000000
combojiang兄在 《透过MmIsAddressValid看Windows分页机制》中也提到PTE的计算公式,如下:

代码:
PTE = ((VA >> 12) << 2 ) & 0x3FFFC + 0xc0000000;
估计combojiang兄深夜发帖,意识模糊 :-),少写了个F,误导了不少群众,还没人指出,正确的应该是:

代码:
PTE = ((VA >> 12) << 2 ) & 0x3FFFFC + 0xc0000000;
这里的& 0x3FFFFC也是不必要的,& 0x3FFFFC只是将低2位清零,而<< 2后低2位本来就是0,所以等价于:

代码:
PTE = (VA >> 12) * 4 + 0xc0000000;

上面说的都是在32位 x86 非PAE的情况下,PAE情况下略有不同,有时间再整理

<think>嗯,我现在要理解页表的概念和实现。首先,页表应该是操作系统内存管理中的一个部分,特别是在虚拟内存管理里。记得之前学过虚拟内存,它允许程序使用比实际物理内存更大的地址空间,对吧?页表应该是用来映射虚拟地址物理地址的结构。 页表可能是指页表中的每一个条目,用来记录虚拟页面和物理页框的对应关系。每个页表可能包含物理页框号,还有一些状态位,比如是否存在内存中、是否被修改过、访问权限等。比如,当程序访问一个虚拟地址时,操作系统会通过页表找到对应的物理地址。如果该页不在内存中,就会触发缺页中断,然后从磁盘调入。 那页表具体是怎么实现的呢?可能需要考虑每个页表的大小。比如,在32位系统里,假设物理地址空间是4GB,那么每个页框的大小通常是4KB,所以物理页框号可能需要20位(因为4GB/4KB=1M个页框,即2^20)。再加上一些控制位,比如存在位、脏位、访问权限位等,可能每个页表需要32位(4字节)。比如,存在位占1位,读写权限占几位,物理页框号占20位,剩下的可能用于其他标志位。 不过不同的系统可能有不同的设计,比如64位系统可能需要更大的页表。另外,多级页表结构可能也会影响页表的实现,比如层次分页可以减少页表的内存占用。例如,x86系统使用多级页表页表的结构可能更复杂,包含指向下一级页表地址或者物理页框号。 页表的作用应该是实现虚拟地址物理地址的转换,支持内存保护,比如读写权限,用户态和内核态的访问控制,还有记录页面的使用情况,比如是否被访问过,是否被修改过,这对页面置换算法很重要,比如在需要换出页面时,选择被修改过的页面可能需要写回磁盘,而未被修改的可以直接丢弃。 可能还有引用位,用于时钟算法或最近未使用算法。此外,页表中的信息还能帮助处理缺页中断,比如通过存在位判断是否需要调入页面。 在实现上,操作系统需要维护每个进程的页表,通常存储在内存中,由MMU(内存管理单元)硬件来加速地址转换。当发生上下文切换时,操作系统会切换页表基址寄存器,指向新进程的页表。这样每个进程都有自己的虚拟地址空间,互不干扰。 不过,如果每个进程的页表都很大,比如在32位系统下,每个进程可能有百万级的页表,这会占用很多内存。因此,多级页表页表的紧凑设计就很重要。例如,使用层次化的页表结构,只有实际使用的部分才会分配内存,节省空间。 另外,页表中的权限位(如用户/超级visor模式)可以防止用户进程访问内核空间的内存,提高系统安全性。还有,通过共享内存的页表设置,不同进程可以共享同一物理页框,实现进程间通信。 总结一下,页表页表的基本单元,存储了虚拟页到物理页框的映射及相关控制信息,实现地址转换、内存保护和页面管理等功能。实现时需考虑结构、大小、多级分页和硬件支持等因素。</think>### 页表的概念与实现 #### 1. **页表的定义** 页表(Page Table Entry, PTE)是页表中的基本单元,用于记录虚拟页与物理页框(Page Frame)的映射关系及控制信息。每个页表对应一个虚拟页,存储以下关键信息[^2][^3]: - **物理页框号(PFN)**:虚拟页对应的物理内存页框地址。 - **存在位(Present Bit)**:标记该页是否已加载到内存中。 - **访问权限位**(如读/写/执行权限)。 - **修改位(Dirty Bit)**:标记该页是否被修改过(决定换出时是否需要写回磁盘)。 - **其他控制位**:如用户/内核模式访问权限、共享标志等。 #### 2. **实现方式** ##### (1)页表结构 以32位系统为例,假设页大小为4KB: - 物理页框号占20位(可寻址$2^{20}$个页框,覆盖4GB物理内存)。 - 控制位占12位(包括存在位、修改位、权限位等)。 - 总大小为4字节(32位),结构示例如下: $$ \text{物理页框号(20位)} \mid \text{保留位(12位)} \mid \text{存在位(1位)} \mid \text{读写位(1位)} \mid \text{用户/内核位(1位)} $$ ##### (2)多级页表 现代操作系统(如x86)采用多级页表减少内存占用。例如,x86-64使用四级页表: 1. **页全局目录(PGD)** 2. **页上级目录(PUD)** 3. **页中间目录(PMD)** 4. **页表(PT)** 每级页表存储下一级页表物理地址,最终指向物理页框[^5]。 ##### (3)硬件支持 - **MMU(内存管理单元)**:负责通过页表完成虚拟地址物理地址的转换。 - **TLB(快表)**:缓存常用页表,加速地址转换[^4]。 #### 3. **核心作用** 1. **地址转换**:将虚拟地址映射到物理地址,支持虚拟内存机制。 2. **内存保护**:通过权限位限制非法访问(如用户进程访问内核空间)。 3. **页面置换支持**:记录访问位和修改位,供页面置换算法(如LRU、Clock)使用[^3]。 4. **共享内存**:多个进程的页表可指向同一物理页框,实现内存共享。 #### 4. **示例:页表在缺页中断中的使用** 当进程访问一个虚拟地址时: 1. MMU查找页表,若存在位为0,触发缺页中断。 2. 操作系统从磁盘加载缺失页到物理内存,更新页表的存在位和物理页框号。 3. 重新执行指令,完成地址转换。 ```c // 简化的页表结构(Linux内核示例) typedef struct { unsigned int pfn : 20; // 物理页框号 unsigned int present : 1; // 存在位 unsigned int writable : 1; // 可写位 unsigned int user : 1; // 用户模式可访问 unsigned int dirty : 1; // 修改位 } page_table_entry; ``` #### 5. **性能与优化** - **页表大小**:直接影响页表内存占用。64位系统可能使用8字节的页表。 - **大页(Huge Page)**:通过增大页大小(如2MB)减少页表层级,提升TLB命中率。 - **反向页表**:以物理页框为索引,减少页表内存消耗(常用于嵌入式系统)。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值