1.内存地址
当使用80x86处理器时,必须区分三个地址
逻辑地址(Logical address):每个逻辑地址包括一个段和偏移,偏移指从段起始地址到实际地址的偏移。
线性地址(Linear address)(也称虚拟地址):一个324GB的地址,通常用十六进制表示,范围从0x00000000到0xffffffff
物理地址(physical address):用于在内存芯片上寻址内存单元。与从CPU
MMU通过一种称为分段单元(segmentation unit)的硬件电路吧逻辑地址转换成线性地址,接着分页单元(paging uni)的硬件电路把线性地址转换成一个物理地址。
内存仲裁器(memory arbiter):这个硬件电路插在总线和每个RAMDMA之间访问RAM2.硬件中的分段
从80286开始,intel(real mode)(protected mode)。实模式存在原因主要是维持处理器与早期模型兼容,不让操作系统自举。
(1)段选择符和段寄存器:一个逻辑地址由两部分组成:一个段标志符和一个指定段内相对地址偏移量。
段标识符是一个16(Segment Selector),32位长字段。
为了快速方便地找到段选择符,处理器提供了段寄存器(),段寄存器有cs,ss,ds,es,fs和gs6个寄存器中有三个有专门用途。
Cs
Ss
Ds Cs寄存器还有一个重要功能,它包含一个两位字段,用以指明CPUCurrent Privilege levelCPL),03代表最低优先级。Linux0级和3
(2)段描述符:
每个段由一个8(Segment Descriptor)Global Descriptor Table,GDTLocal Descriptor TableLDT)中。
通常只定义GDT,GDT中的段之外,如果还需创建附加的段,就可以有自己的LDTGDT存放在gdtrLDT地址和大小放在ldtr
下面几种类型的段在Linux中广泛使用。
代码段描述符:表示这个段描述符代表一个代码段,它可以放在GDTLDT中,置S1(非系统段)
数据段描述符:表示一个数据段,可以放在GDTLDT中,S标志为1
任务状态段描述符(Task State Segment,TSSD
局部描述符表描述符(LDTDGDT中。
(3)快速访问段描述符
为了加速逻辑地址到线性地址的转换,80x86提供了一个附加的不可编程的寄存器,供68个字节的段描述符。每当一个段选择符被装入段寄存器时,相应的段描述符就由内存装入对应的非编程的CPUGDTLDT。除非段寄存器内容有改变时。
段选择符字段:
Index(13bit): 指定放在GDTLDT的相应段描述符的入口。
TI(1bit):Table IndicatorGDT还是LDT
RPL(2bit):请求中特权级.
能保存在GDT2*13方-1=8191
(4)分段单元
分段单元执行以下操作:
①先检查段选择符的TIGDT还是LDT
②从index字段计算段描述符的地址,index*8+gdtr/ldtr
③逻辑地址偏移量与段描述符的Base
3.Linux中的分段
80x86微处理器的分段,鼓励程序员把他们的程序化分成逻辑上的相关的实体,如子程序或者全局与局部数据区。而Linux基本不采用分段机制。Linux
①当所有进程使用相同的段寄存器值时,内存管理变得更简单。
Linux设计目标之一,是可以移植到绝大多数流行的处理器上,RISC体系结构对分段的支持分有限。
2.6Linux只有在80x86
Linux进程都使用一对相同的段来寻址,即用户代码段,用户数据段。
Linux进程都使用一对相同段寻址,内核代码段,内核数据段。
四个主要Linux段的段描述符字段的值
4.硬件中的分页
分页单元(paging unit)把线性地址转换成物理地址,其中一个关键任务是把所请求的访问类型与线性地址的访问权限相比较,如果这次内存访问是无效的,就产生一个缺页异常。
把线性地址映射到物理地址的数据结构叫页表(page table),页表在主存中,在启动分页单元之前必须由内核对页表进行适当的初始化。
(1)常规分页
从80386起,intel4KB的页,323个域:
Directory(页目录),最高10
Table(页表),中间10
Offset(偏移量),最低12
线性地址的转换分两步,每一步都基于一种转换表,第一种是页目录表(page directory),第二种是页表(page table).
每个活动进程必须有一个分配给它的页目录,只有在进程实际需要一个页表时,才给该页表分配RAM
正在使用的页目录的物理地址放在cr3Directory字段决定页目录中的目录项,Table字段决定页表中的表项,表项含有页所在页框的物理地址。Offset字段决定页框内的相对位置。
假设进程需要读线性地址0x20021406的字节,分页单元做如下处理:
①Directory字段的0x800x80目录项,此目录项指向和该进程的页相关的页表。
②Table字段0x210x21表项,此表项指向包含所需页的页框
③最后,Offset字段0x4060x406中的字节。
(2)扩展分页
从Pentium模型开始,80x86(extended paging),4MB,而不是4KB(3) 64位系统中的分页:
所有64Linux64位平台硬件分页系统特征,
(4)硬件高速缓存
动态RAM(DRAM)芯片的存取时间是时钟周期的数百倍,这意味着,访问RAMCPU可能要等待很长时间,为了缩小CPURAM之间的速度不匹配,引入了硬件高速缓存内存(hardware cache memory),硬件高速缓存基于著名的局部性原理(locality principle),该原理既适用程序结构也使用数据结构。
多处理器系统的每一个处理器都有一个单独的硬件告诉缓存,因此需要额外的硬件电路用于保持高速缓存内容的同步。
(5)转换后援缓冲器(TLB)
除了通用硬件高速缓存之外,80x86处理器还包含了另一个TLB(Translation Lookaside Buffer)的高速缓存用于加快线性地址的转换。
当一个线性地址第一次使用时,通过慢速访问RAMTLBTLB entry)中,以便以后对同一个线性地址的引用得到快速转换。
在多处理器系统中,每个CPUTLB,这叫该CPUTLB
5.Linux中的分页
(1)到2.6.10版本,Linux2.6.11版本开始,采用了四级分页模型:
页全局目录(Page Global Directory)
页上级目录(Page Upper Directory)
页中间目录(Page Middle Directory)
页表(Page Table)
对于没有启用物理地址扩展的32Linux通过使“页上级目录”位和“页中间目录”位全为03264位系统都能使用。
(2)Linux的进程处理很大程度上依赖于分页,事实上线性地址到物理地址的自动转换使下面的设计目标变得可行
①给每个进程分配一块不同的物理地址空间,这确保了可以有效地防止寻址错误。
②区别页()和页框()之不同,这就允许存放在某个页框中的一个页,然后保存到磁盘上,以后重新装入这同一页时又可以被装载不同的页框中,这就是虚拟内存机制的基本要素。
(3)进程页表
进程的线性地址空间分成两部分
从0x00000000~0xbfffffff的线性地址,无论进程运行在用户态还是内核态都可以寻址。
从0xc0000000~0xffffffff的线性地址,只有内核态进程才能访问
(4)事实上每个内核线程并不拥有自己的页表集,更确切的说,它使用一个普通进程的页表集。