Windows内存管理-分段
0x00前言
这是《深入解析Windows Kenrel》系列文章的第1章 第二篇
0x01原因
分段的产生原属于安全问题。
一个程序可以自由的访问不属于它的内存位置,甚至可以对那些内容进行修改。这也导致安全问题 促使一种内存隔离的手段 分段的产生。
0x02分段原理
处理器要求在加载程序时,先定义该程序所拥有的段,然后允许使用这些段。定义段时需要基地址,段界限,特权级别,类型等。
在一个程序访问cs,ss,ds,es 这些段时。处理器将会实施检查,防止内存违规访问。
因此有了段描述符来描述这些段的内容和权限
0x03段描述符
认识段描述符先定义全局描述符表GDT,为了跟踪GDT 处理器有一个48位寄存器,也就是gdtr,分别是32位线性地址和16位边界地址
访问地址范围就是0x00000000到0xffffffff 4gb 的映射范围 界限地址 ffff 就是64kb 一个GDT大小是8个字节 所以GDT最最多可以定义8192个描述符
下面就是段描述符格式
看到当前的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