首先,我先澄清三个地址概念:logical address, linear address, physical address。我从地址转换的角度来说明三种地址之间的关系。
地址转换的含义是:从logical address(程序员角度的地址)转换为physical address(实际的物理地址),这个过程可以分为两步:
- Segment translation:logical address(包含segment selector和segment offset)转换为linear address
- Page Translation:linear address转换为physical address(如果PG set以后)
Segment Translation
为了进行这个转换,需要一些数据结构的支持:
- Descriptors
- Descriptor tables
- Selectors
- Segment Registers
Descriptors
- BASE:在一个descriptor中,BASE被分为三部分放在其中,组成一个32 bits,表示Segment的位置
- LIMIT:segment的size
- Granularity bit:units-1 byte or 4 kilobytes
- TYPE:descriptor的类型
- DPL:描述符的优先级
- Segment-Present bit:zero-valid,Segment不在memory或者没有被映射
- Access bit:
Descriptor Tables
GDT和LDT的关系
- GDT:全局描述符表,它每一项都代表一个segment,甚至是一个LDT(这一也是一个段,在内存中)
- LDT:针对某个程序或者任务的描述符表
Selectors
Selector的功能是指示某一个描述符表,和对应其中某项的Index——共16位
- INDEX:表内索引-12
- TI:Table Indicator,可以是GDT也可以是LDT-1
- RPL:请求的优先级,会和相应描述符代表segment的优先级做比较-3
Segment Register
包含CS,SS,DS,ES,FS,GS,每个寄存器包含两部分,一部分是invisible part, selector(由用户程序操作),领一部分是隐藏部分(由processor操作)
加载这些寄存器的方式有两种:
- 直接加载:mov,pop,LDS,LSS,LGS,LFS
- 隐式加载:jmp,call
使用这些指令以后,程序加载visible part with a selector,processor自动加载相应描述符的base,limit,type等
这样Segment Register有cache的作用,比如CS,DS这些经常使用的段,会直接将base address加上
怎么知道要使用哪一个段的(selector从哪里来)
Page Translation
这里将linear address分成了三部分,DIR,PAGE,OFFSET;这样可以从一个二级页表,找到相应的物理页和数据
Page translation可以设置on-chip cache,这对程序员是不可见的,但是对系统程序员是可见的。Operating-system程序员在页表改变的时候必须刷新cache
- cr3直接被修改
- 切换task
Combining Segment and Page Translation
"Flat" Architecture
80386机器会被使用去执行一些
不要Segment的软件
,但是80386并不提供关闭Segment的机制。所以80386设计了专门的Segment Registers,当程序不需要Segment概念时,使用这个寄存器,这个寄存器值不变化,程序的logical address可以涉及所有的physical address。
Segment Spanning Several Pages
80386体系结构是允许Segment的大小比Page大或者小的。对于一片较大的区域,如果需要统一设置和管理,那么可以设置一个大的Segment
Pages Spanning Several Segment
一些小的数据结构需要单独赋予保护和其他服务,比如semaphore,需要保护,但是其实所占空间很小,分配一个页是没有必要的。