• Windows内存管理分段


    0x01原因

    分段的产生原属于安全问题。

    一个程序可以自由的访问不属于它的内存位置,甚至可以对那些内容进行修改。这也导致安全问题 促使一种内存隔离的手段 分段的产生。

    0x02分段原理

    处理器要求在加载程序时,先定义该程序所拥有的段,然后允许使用这些段。定义段时需要基地址,段界限,特权级别,类型等。

    在一个程序访问cs,ss,ds,es 这些段时。处理器将会实施检查,防止内存违规访问。

    因此有了段描述符来描述这些段的内容和权限

    0x03段描述符

    认识段描述符先定义全局描述符表GDT,为了跟踪GDT 处理器有一个48位寄存器,也就是gdtr,分别是32位线性地址和16位边界地址

    访问地址范围就是0x00000000到0xffffffff 4gb 的映射范围  界限地址 ffff  就是64kb  一个GDT大小是8个字节 所以GDT最最多可以定义8192个描述符

    下面就是段描述符格式

    下面是低位,上面是高位
    段基地址:
    0-15+16~23+24~31 FFFF FF FF
    段界限
    0-15+19+16 FFFF F
    0xFFFF FFFF:0FFFF 就是GDT的物理地址
     
    G粒度位
    当为0时 段界限以字节为单位 范围(1b~1mb) 当为1时,段界限以4KB为界限 范围(4kb-4gb)
    S描述符位:
    当为0时 表示是个系统段,当为1时表示代码段或者数据段(栈段也是特殊的数据段)
    DPL特权级位:
    分别表示0,1,2,3 其中0是最高位。不同级别的程序相互隔离,严格限制互访。高可以访问低特权级
    P段存在位:
    p位表示描述符对应的段是否存在,当内存紧张时,可能只建立了描述符没有建立内存这时P位就是0 表示段并不存在,p是有处理器负责检查的 如果是0处理器会产生一个中断。这一过程由操作系统提供,负责将该段从硬盘换回内存。将p置为1,在多任务多用户的系统中,这是一种常用的虚拟内存调度策略
    D/B操作数大小位或者栈指针大小位或者上部边界标志位
    不同段表示不同意思
    代码段表示 d=0 表示16位 d=1 表示32位 表示使用 eip还是ip
    栈段表示 b=0表示使用sp b=1 表示使用 esp
    b位也决定上部边界 b=0 就是 sp寄存器最大值 0xffff b=1 esp最大值 0xffff ffff
    L64专用位
    暂时不涉及 置0即可
    TYPE 描述符子类型位
    对于数据段来说
    4位 X,E,W,A
    代码段
    4位 X,C,R,A
    x表示可执行 数据段不可执行 默认为0
    数据段的E表示段扩展方向 为0向上扩展 向高地址方向扩展。 为1向下扩展 向低地址扩展通常是栈段。
    W=0表示不允许写入
    C表示特权级依从 0表示非依从的代码段,可以从与它特权级相同的代码段调用,或者通过门调用
    1表示 允许从低特权级的程序转移到该段执行。
    R=0表示不能读出
    A位已访问位 表示最近这个段是否被访问过 每当被访问会被置1 清理由操作系统负责 监视是否还在使用。知道使用频率,内存紧张时把不常用的段退避到硬盘上,从而实现虚拟内存管理
    AVL位
    软件位 用户使用没啥用
     
    下面通过windbg调试查看gdt表

     看到当前的gdtr 寄存器值 和当前 ds cs es值

     ds 是23解析规则就是

    2        3

    0010 0011

    00100=4

    rpl 请求特权级  3就ring3 权限

    tl 0=gdtr 寄存器里面  1=ldtr里面 

    ds=23 指的就是GDT表的第5位置 下标在4

     可以看到前5个除了第一个用于指向null的gdt 表 其他的4个把所有类型都包括了 这是因为 微软没用分段来隔离内存  因为gdt 大小只能8192个太少了 。

    读取少字节时性能不高,后面改用分页来隔离内存了,又犹豫cpu只认段描述符这种格式,所以就做了4个把所有类型都包括的描述符 来解决这个问题。

    但是fs gs 用的还是分段

    这里fs=3b  

    111011= 7

     f892a000~00001fff

    看内存拆分就是

    01 00 00 a0  92 93 c0 f8

    00 0a 92 f8-01

    g位为1  所以  段界限要*4kb=4096

    00 00 01*4kb+0xfff 就是最后的段界限

    最后就是

    f892a000~1fff

    从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。
  • 相关阅读:
    CSRF 1 (转)
    学习笔记-静态SQL和动态SQL
    学习笔记-oracle-PL/SQL-动态游标
    spring框架介绍以及简单使用
    SpringMvc的常用注解
    tcp的三次握手个四次挥手
    大量面试题
    Comparable和Comparator接口
    JVM介绍
    JVM类加载
  • 原文地址:https://www.cnblogs.com/feizianquan/p/15676608.html
Copyright © 2020-2023  润新知