zoukankan      html  css  js  c++  java
  • 操作系统存储管理(5)IA32/Linux的地址转换

    IA-32/Linux按字节编址;在保护模式下,IA-32采用段页式虚拟存储管理方式,存储地址采用逻辑地址、线性地址和物理地址来进行描述。
    逻辑地址由48位组成,包含16位段选择符(高13位为段表项的index)和32位段内偏移量(有效地址=基址寄存器+变址寄存器×比例因子+偏移量),通过段描述符取到段表中的对应段表项的段基址,加上有效地址得到线性地址(位数由虚拟地址空间大小决定)。
    PS:逻辑地址和线性地址是虚拟地址的两种不同表示形式,描述的都是4GB虚拟地址空间中的一个存储地址。
    最后通过分页方式转换为物理地址(位数由存储器总线的地址线条数决定)
     
    逻辑地址向线性地址的转换:
    6个16位段寄存器,用于存放段选择符
    CS(代码段):程序代码所在段
    SS(栈段):栈区所在段
    DS(数据段):全局静态数据区所在段
    其他3个辅助段寄存器ES、GS和FS可指向任意数据段
    TI=0,选择全局描述符表(GDT);TI=1,选择局部描述符表(LDT)
    每个段寄存器都有一个RPL字段(Request Privilege Level),说明的是进程对段访问的请求权限。
    RPL是当前程序段的特权等级,Linux只用了0级和3级:RPL=00,为第0级,位于最高级的内核态;RPL=11,为第3级,位于最低级的用户态。当前CPL=0的进程要访问一个数据段,它把段选择符中的RPL设为3,这样它对该段仍然只有特权为3的访问权限。
    CS寄存器中的RPL字段表示CPU的当前特权级(Current Privilege Level,CPL)
    高13位索引用来确定当前使用的段描述符在描述表(段表)中的位置,即段表项的index
    段描述符实际就是段表项,分两类:
    • 普通段:用户/内核的代码段和数据段描述符
    • 系统控制段描述符,又分两种:
    1. 特殊系统控制段描述符,包括:局部描述符表(LDT)描述符和任务状态段(TSS,每一个进程的状态描述信息)描述符   
    2. 控制转移类描述符,包括:调用门描述符、任务门描述符、中断门描述符和陷阱门描述符(门:中断服务程序的首地址)
    每项段描述符共64位,包括:
    B31~B0: 32位基地址; 
    L19~L0:20位限界,表示段中最大页号
    G:粒度。G=1以页(4KB)为单位;G=0以字节为单位。因为界限为20位,故当G=0时最大的段为1MB;当G=1时,最大段为4KB×2^20 =4GB
    D:D=1表示地址和数据(段内偏移量)为32位宽,D=0表示16位宽
    AVL:由操作系统定义使用,Linux未使用
    P:P=1表示存在于主存,P=0表示不存在。Linux总把P置1,不会以段为单位淘汰
    DPL:访问段时对当前特权级CPL的最低等级要求。即,只有CPL为00时才可访问DPL为00的段,任何进程都可访问DPL为11的段
    S:S=0系统控制描述符,S=1普通的代码段或数据段描述符
    TYPE:段的访问权限或系统控制描述符类型
    A:A=1已被访问过,A=0未被访问过。(通常A包含在TYPE字段中,相当于脏位)
     
    描述表实际就是段表,有三种类型:
    • 全局描述符表GDT:只有一个,用来存放系统内每个任务共用的描述符,例如,内核代码段、内核数据段、用户代码段、用户数据段以及TSS(任务状态段)等都属于GDT中描述的段
    • 局部描述符表LDT:存放某任务(即用户进程)专用的描述符
    • 中断描述符表IDT:包含256个中断门、陷阱门和任务门描述符
    为支持分段机制,CPU中有多个用户不可访问的内部寄存器,操作系统通过特权指令可对寄存器TR、LDTR、GDTR和IDTR进行读写
    每次段寄存器装入新选择符时(例如更换进程的时候CS换新段选择符),新描述符装入描述符cache,在逻辑地址到线性地址转换时,MMU直接用描述符cache中的信息,不必访问主存段表
    TR(任务寄存器)存放TSS描述符的段选择符;LDTR(LDT寄存器)存放LDT描述符的段选择符 
    PS:复习的时候注意段选择符和段描述符的区别。TR和LDTR放的是TSS描述符和LDT描述符的段选择符。TSS描述符和LDT描述符在GDT中。
    GDT和IDT首地址、限界放在GDTR和IDTR中
     
    举例:Linux中的全局描述符表(GDT)
    如TSS和LDT的段选择符分别为0x88和0x80:
    TR放了0x80,RPL=0,说明TR所指段TSS处于第0环;TI=0,其描述符在GDT中;索引值为0x0010,是第16项
    LDTR放了0x88,RPL=0,说明LDTR所指段LDT处于第0环;TI=0,其描述符在GDT中;索引值为0x0011,是第17项
     
    图中,其实只有第一次需要去GDT表中找段描述符,后来就去Cache中找了。
     
    Linux为了移植到RISC处理器,简化了分段机制,在初始化时将所有段描述符的基址设为0来简化,每个段都被初始化在0~4GB的线性地址空间中。线性地址就是有效地址。
    P必定为1
    GDT的第12-15表项分别是内核代码段、内核数据段、用户代码段、用户数据段。每个段描述符8B。
    因此执行内核代码的时候,CS里总是0x60,DS里总是0x68,以及最后三位000
    执行用户程序的时候,CS里总是0x73,DS里总是0x7b,以及最后三位011
     
    线性地址向物理地址的转换:
    控制寄存器保存机器的各种控制和状态信息,它们将影响系统所有任务的运行,操作系统进行任务控制或存储管理时使用这些控制和状态信息。
    • CR0:控制寄存器
    ① PE:1为保护模式。一旦在保护模式,不能再将PE清0,只能重启系统以回到实模式。
    ② PG:1为启用分页;0为禁止分页,此时线性地址被直接作为物理地址使用。
    若要启用分页机制,则PE和PG都要置1。
    ③ 任务切换位TS:任务切换时将其置1,切换完毕则清0,可用CLTS指令将其清0。
    ④ 对齐屏蔽位AM。AM=0则禁止对齐检查;AM=1且EFLSGS的AC=1则进行对其检查
    ⑤ cache功能控制位NW(Not Write-through)和CD(Cache Disable):只有当NW和CD均为0时,cache才能工作。
    • CR2:页故障(page fault)线性地址寄存器
    存放引起页故障的线性地址。只有在CR0中的PG=1时,CR2才有效。 
    • CR3:页目录基址寄存器
    保存页目录表(第一级页表)的起始地址。只有当CR0中的PG=1时,CR3才有效。
    IA-32采用两级页表方式:
    4GB=1K个子空间×1K个页面/子空间×4KB/页
    32位线性地址:1K个页目录项,通过10位页目录索引找到;每个页表1K页表项,通过10位页表索引找到;每页4KB,通过12位页内偏移量找到。
    P:1表示页表或页在主存中;P=0表示页表或页不在主存,即缺页,此时需将页故障线性地址保存到CR2。
    R/W:0表示页表或页只能读不能写;1表示可读可写。
    U/S:0表示用户进程不能访问;1表示允许访问。
    PWT:控制页表或页的cache写策略是全写(Write Through)还是回写(Write Back)。
    PCD:控制页表或页能否被缓存到cache中。
    A:1表示指定页表或页被访问过,初始化时OS将其清0。利用该标志,OS可清楚了解哪些页表或页正在使用,一般选择长期未用的页或近来最少使用的页调出主存。由MMU在进行地址转换时将该位置1。
    D:脏位dirty bit。第一级页表页目录项中的脏位无意义,只在第二级页表页表项中有意义。初始化时OS将其清0,由MMU在进行写操作的地址转换时将该位置1。
    高20位是页表或页在主存中的首地址对应的页框号,即首地址的高20位。每个页表的起始位置都按4KB对齐。
    举例:IA-32/Linux中,执行“movl 8(%ebp), %eax”时,源操作数的逻辑地址向线性地址转换的过程如下:
    (1)若CPL>DPL则越级,否则计算有效地址EA=R[ebp]+0×0+8
    (2)取出段寄存器DS对应的描述符cache中的段基址(Linux中段基址为0)
    (3)线性地址LA=段基址+EA=EA,若LA>段限则越界(Linux肯定不会,段限是全1)
    (4)将LA转换为主存地址A
    -    若访问TLB命中则地址转换得到A;否则处理TLB缺失(硬件/OS)
    -    若缺页或越权(R/W不符)则调出OS内核;否则地址转换得到A 
    -    根据A先到Cache中找,若命中则取出A在Cache中的副本 
    -    若Cache不命中,则再到主存取A所在主存块送对应Cache行
     
    Intel Core i7的线性地址转换:
     
    页表变为了4级页表,每级虚页号9位。
    进程切换时,从mm结构的pgd获得进程对应第一级页表的首地址放入CR3。
    虚拟地址VA变为了48位。其中虚页号36位,页内偏移量12位。物理地址可以远大于虚拟地址。
    页表项PTE从32位4B变为了64位8B。因此项数从1024变为了512。
    显存不需要地址转换。
  • 相关阅读:
    VS2005快捷键(转)
    codeSmish使用《转》
    WinForm TextBox数据绑定
    NetTiers抛出"Unable To Load NetTiersServiceSection“的异常
    DELPHi第三方控件使用方法(摘录)
    遠程連接操作
    不同服务器数据库之间的数据操作
    delphi 关闭 MDI 子窗体
    VSS使用手册(转)
    delphi 快捷键
  • 原文地址:https://www.cnblogs.com/yangyuliufeng/p/9205733.html
Copyright © 2011-2022 走看看