• 内核知识第八讲,PDE,PTE,页目录表,页表的内存管理


          内核知识第八讲,PDE,PTE,页目录表,页表的内存管理

    一丶查看GDT表.

    我们通过WinDbg + 虚拟机可以进行双机调试.调试一下看下GDT表

    我们知道,GDT表中.存储的是存储段信息. 保存了一系列的段和内存的属性.

    但是微软并没有使用.

    我们可以通过ring3的段寄存器. 当作GDT表的下标.进行查表. 查询GDT表.

    例如我们用OD随便打开一个ring3的exe,然后看下段和虚拟地址.:

    虚拟地址: 0040256f  段选择子: cs:1B

    那么此时段选择字当下表.虚拟地址当作偏移.去查询GDT表

    下图为选择子结构

    段选择子结构:

     首先先拆分选择子.

    1B =   0000000000011 011

    查询出来下表为3,那么去GDT表的第三项进行查找.

    然后我们从中取出段首地址 加上我们的偏移

    00000000  + 40256F = 0040256F(线性地址)

    那么通过查询GDT表.那么可以找到线性地址. 而我们GDT表,微软没有使用它来进行进程隔离. 

    PS: 微软因为不使用GDT表进行进程隔离,所以段选择子都是一样的.基地址都是0,我们的虚拟地址就是线性地址.

    如果没有开分页保护.那么就是物理地址了.但是注意FS寄存器. FS寄存器很特殊.并不能说GDT表没用.

    二丶控制寄存器CR0

    我们上面说过.如果没有开启分页保护.那么虚拟地址就是线性地址,线性地址就是物理地址

    而微软是通过分页进行进程内存的隔离的.

    首先说一下什么分页的历史,和CR0控制寄存器.

    在保护模式下, 寄存器CR0的高位1表示开启分页.0表示不开启.

    而这个在操作系统初始化的是否就已经完成了.

    如果我们不开启,那么访问虚拟内存,就等价于访问物理内存了.

    但是我们的三环是不可以操作的.这个属于特权指令.如果用汇编进行操作.例如:

    __asm mov cr0,8000000

    程序会崩溃,提示你权限不够,并且报告错误码为 C096

    但是我们0环可以进行操作的.

    看一下CR0的结构:

    但是我们0环可以进行操作的.

     

    此图是从inter手册上截图下来的.有兴趣的可以查询CR0查看.

    刚才我们说的高位为1的是否就去掉分页保护,此时访问虚拟内存 等价于访问物理内存,其实我们修改的是PG位

    关于位怎么说的,inter手册也说.这里我总结一下重要的,如果不相信我可以查看inter手册.

    PG:  PG位表示是否分页管理机制是否有效. PG = 1,有效, PG = 0 无效.

    WP: Wp位 写保护位, WP为0禁用写保护,为1则启动  

    PS: 通过修改WP位可以进行过保护. 详情请看 https://www.cnblogs.com/hongfei/archive/2013/06/18/3142162.html 转载

    三丶分页管理机制

    讲解分页管理机制之前,我们要明白以下几个关键词的意思.

    页码:

      在80386下,一个页的固定大小是4K个字节,也就是4096,一个页的辩解地址,不许死4K的倍数.

    所以4G大小的内存.就可以划分为1M个节. 而我们的页的开始一般具有一个特点.

    比如我们的虚拟地址:

      004010123,而页的首地址是00401000

    后12位都是0.

    所以我们把页的高20位称为页码.

    进程内存的保护.

    进程内存的保护就通过页的方式进行保护的.

     当我们的线性地址转化为物理地址的是否,会进行查表. 进而查询到物理地址是那个.

    微软采用的是这种方式.

     线性地址转物理地址需要注意的页问题.

    这个问题则是页的映射.

    我们知道,页码是高20位,那么低12为就是偏移了.

    当32位的线性地址转为32为的物理地址的是否,只需要记录页码就可以了.低12位都是一样的.所以不用记录.

    比如线性地址:

      004010123 映射到物理地址 002010123

    那么我只需要记录前20位即可.

      004010  -> 002010   ,然后物理地址加上我们的后12位即可. 002010+123 = 002010123

    四丶线性地址到物理地址的转换.

    我们说过,操作系统为了隔离内存.采用了分页管理.而我们线性地址转化到物理地址的时候.

    则需要查表.

    那么我们觉着这个表应该怎么做?

    物理地址

    Xxxx

    内存保护属性

     类似于这样,我们只需要让虚拟地址当标进行查表即可.

    我们每一个进程都提供这样的一张表.但是在那个时代.资源是匮乏的.我们这样做.开不了几个进程内存就会耗光了.

    所以微软提供了自己的表.而硬件上也提供了支持.

    我们看下微软的表.

    首先我们的CR3寄存器保存了表的首地址.

    这里有一个页目录表,还有页表的关键词.

    页目录表: 也称为PDE,而页表称之为PTE.

    CPU会通过虚拟地址,当作下表.去页目录表中查询.然后查到的结果再去页表中查询.这样就查到对应的物理地址了.

    PDE表的大小:

      页目录表,存储在一个4K字节的物理页中,其中每一项是4个字节.保存了页表的地址.

      而最大是1M个页.

    PTE表的大小.

      PTE的大小也和PDE一样的.

    微软为什么这样设计.有人会问.这样设计不就资源用的更多了吗.其实不是的. 虽然我们设计怎么大.

    但是通过两个表查询.可以映射4G内存.而上面的设计方法不行.

     

    首先前边20位保存了页表或者物理地址的基地址.

    比如我们的页目录表. 查到了第5项.那么从中取出千20位来,加上000就等于页表了. 

    然后从页表中查询千20位.+虚拟地址的偏移就等价于实际的物理地址了.

    AVL 位: 可利用位.

    D    位: 表示这个分页是否写过.

    A   位: 表示这个分页是否读过

    U/S位: 表示这个分页是否用户可以访问还是ring0可以访问.

    R/W位: 内存保护位. 可读可写可执行. 还是可读可执行.

    P   位:   内存是否有效.

    R/W位: 注意我这里说的有两种方式. 可读可执行,和可读可写可执行.  有没有发现,我们的Ring3程序.不过是那个内存区域也好.都是可以读的.

    而我们Ring3下的修改内存分页保护属性,其实就是将这个页表的这个RW位进行置位.

    而我们的虚拟地址当作下表进行查表. 我们的虚拟地址不是分为了20位了吗. 前10位当作 页目录表的下表. 后10位当作页表的下表

    设有物理地址为:

      00401 000

    那么下表则为:

      00401 = 0000000001 0000000001

    通过虚拟地址得知,页目录表是第一项,而页表也是第一项.

    设页目录表第一项为

        003f0111,  此时页表为 取前20位,加上3个0.  003f0 + 000 = 003f0000

    设页表为
            00201456, 此时取出前20位加上虚拟地址的后边20位偏移 物理地址= 00201 + 000 = 00201000,那么物理地址就是201000

    图示:

      

    设虚拟地址为00402567H, 取出前20位. 分为高10位,和低10位做 PDE,和PTE的索引.

    然后进行查表.

    最后的通过PTE查询的高20位加上原虚拟地址的低12位, 然后就找到了物理地址.

  • 相关阅读:
    Nginx 服务器安装及配置文件详解
    Linux 之 压缩解压缩
    RPM方式安装MySQL5.6
    Linux 之 搜索
    zabbix客户端安装
    JAVA输出指定目录下的子目录和子文件
    LoadRunner 11 安装破解
    SVN合并操作实践
    (转)SVN分支/合并原理及最佳实践
    MYSQL 免安装版(windows 7/64)
  • 原文地址:https://www.cnblogs.com/iBinary/p/8307728.html
Copyright © 2020-2023  润新知