跳转至

Linux运行的硬件基础

Linux运行的硬件基础

i386的寄存器

i386 -> 80386

  • 通用寄存器

  • EAX: add

  • EBX: base
  • ECX: count
  • EDX: data
  • ESP: stack pointer
  • EBP:base pointer
  • ESI: source index
  • EDI: destination index

通常存32位数据

  • 与16位兼容:低位->8个16位寄存器。AX\BX\...\DI
  • 与8位兼容:进一步将EAX\EBX\ECX\EDX低位16位,分为8位高位字节和8位低位字节,作为8个8位寄存器(AH、BH、CH、DH 和AL、BL、CL、DLhigh low
  • 对8位和16位寄存器的操作只影响相应的寄存器

  • 段寄存器

  • CS: code

  • DS: data
  • SS: stack
  • ES \ FS \ GS: 附加

  • 状态和控制寄存器

  • EFLAGS: 标志寄存器

    • TF:自陷标志
    • 1:单步执行,执行完成可能产生异常1的自陷(每执行完一条指令都由异常1处理程序(debug())进行检验)
    • 0:且将断点地址装入调试寄存器DR0~DR3 时,才会产生异常1 的自陷
    • IOPL: 输入输出特权等级,保护模式下
    • 两位:取值1、2、3、4(级别)
    • Linux内核:0(内核级)3(用户级)
    • CPL(当前特权级) > IOPL: IN、OUT、INS、OUTS、STI、CLI 和LOCK 等指令而不会产生异常13(即 保护异常)
    • CPL == 0: POPF(pop from stack top flags)和中断返回指令可以改变IOPL的值
    • IF(interrupt flag)
    • 1:允许CPU接收外部中断请求
    • 0:禁止外部中断
    • 在保护模式下,只有当第12、13 位指出当前CPL 为最高特权级时,才允许将新值置入标志寄存器(EFLAGS)以改变IF 位的值
    • DF: 定向标志
    • ESI or EDI增值或者减值
    • 1:减
    • 0:增
    • NT:嵌套任务标志位
    • 保护模式下使用
    • 发生中断或者执行CALL,可能引起任务切换(NT:1 else NT:0)
    • VM:虚拟8086方式标志
    • 1:保护模式,使全部段操作就像是在8086 CPU上运行一样
  • EIP: 指令指针寄存器,存放下一条将要执行指令的offset,与目前正在运行的CS存放的基地址->下一条指令的地址(低16位可以分开来访问,指令指针IP寄存器,用于16位寻址)

  • 4个控制寄存器:CR0、CR1、CR2、CR3

    • CR3 是页目录基址寄存器,保存页目录表的物理地址。页目录表总是放在以 4KB 为单位 的存储器边界上,因此,它的地址的低 12 位总为 0,不起作用
  • 系统地址寄存器

保存操作系统要保护的信息和地址转换表信息

  • 任务状态寄存器:16位,保存TSS段的16位选择符
  • 调试和测试寄存器

内存地址

  1. 逻辑地址:段 + 偏移量
  2. 线性地址(虚拟地址):32位unsigned int,4GB,取值范围0x00000000~0xffffffff
  3. 物理地址:内存单元的实际地址,32位unsigned int

段机制和描述符

描述符:描述段的属性,8字节的存储单元

  • 实模式下:代码段、数据段、堆栈段、段的起始地址、段的长度

  • 保护模式:复杂一些

  • (用户)段描述符:32位基地址和20位段界限

  • G:粒度位

    • 0:一个段最长可达1M字节
    • 1:一个段最长可达1M乘以4K = 4G字节
  • D:缺省操作数的大小

    • 0:操作数为:16
    • 1:操作数为:32
  • 第6个字节其余两位为0,为了与将来的处理器兼容

  • 第5个字节:存取权字节

    • P:存在位(Present),表示段描述符描述的这个段是否存在内存中

    • 1:在

    • 0:不在

    • DPL:描述符特权等级,确定保护等级

    • S:system,表示这个段是系统段还是用户段

    • 0:系统段

    • 1:用户程序的代码段、数据段、堆栈段

    • 类型:

    • 第3位:E(execute)表示是否可执行
      • 0:数据段描述符
      • 第2位ED:扩展方向
        • 0:向地址增大的方向扩展,存取数据段中的数据的偏移量必须小于或等于段界限
        • 1:向地址减小的方向扩展,偏移量必须大于界限
      • 第1位W:可写
        • 0:不能写
        • 1:可写入
      • 在80386当中,堆栈段也被看成特殊的数据段
      • 1:代码段描述符
      • 第2位C:一致位
        • 1:如果当前特权级(CPL)低于描述符特权级,并且当前特权级保持不变,那么代码段只能执行
      • 第1位R:可读
        • 0:不能读
        • 1:可读
    • 第0位:A访问位,用于请求分段不分页的系统中,每当该段被访问时,将A 置1。对于分页系统,则A 被忽略未用
  • 系统段描述符

    • 系统段描述符的第5 个字节的第4 位为0,说明它是系统段描述符,类型占4 位,没有A 位。第6 个字节的第6 位为0,说明系统段的长度是字节粒度,所以,一个系统段的最大长度为1M 字节
    • 类型(16种)

  • 描述符表

  • 各种各样的用户描述符和系统描述符,都放在对应的全局描述符表、局部描述符表和中断描述符表中

  • 8的倍数的存储器空间:空间大小在8 个字节(至少含一个描述符)到64K 字节(至多含8K)个描述符之间
  • GDT:除了任务门,中断门和陷阱门描述符外,包含着系统中所有任务都共用的那些段的描述符。它的第一个8 字节位置没有使用
  • IDT:包含256 个门描述符,能包含任务门、中断门和陷阱门描述符,只能存取2K字节以内的描述符,即256 个描述符,这个数字是为了和8086 保持兼容
  • LDT:每个任务各自有一个的LDT,可以使给定任务的代码、数据与别的任务相隔离

    • 每一个任务的局部描述符表LDT 本身也用一个描述符来表示,称为LDT 描述符,它包含了有关局部描述符表的信息,被放在全局描述符表GDT 中
  • 选择符与描述符表寄存器

  • 实模式下:段寄存器存放的是真实的段地址;保护模式下:段寄存器(16位无法存32位的段地址)存放的是段选择符

  • 选择符

    • TI:1的时候,从局部描述符表中取描述符;0的时候,全局描述符表
    • RPL(requestor):请求者特权级,表示描述符的特权级,只有请求者特权级RPL 高于(数字低于)或等于相应的描述符特权级DPL,描述符才能被存取,实现一定程度的保护
  • 段描述符高速缓冲寄存器

    当选择符的值改变时,处理器自动装载不可见部分

  • 寻址过程

  • 描述符投影寄存器

  • Linux的段

  • 从2.2 版开始,Linux 让所有的进程(或叫任务)都使用相同的逻辑地址空间,因此就没有必要使用局部描述符表LDT。但内核中也用到LDT,那只是在VM86 模式中运行Wine 时,即在Linux 上模拟运行Windows 软件或DOS 软件的程序时才使用

  • TI=0,并把这4 个段都放在GDT中, index 就是某个段在GDT 表中的下标
  • 内核代码段和数据段具有最高特权,因此其RPL为0,而用户代码段和数据段具有最低特权,因此其RPL 为3
  • GDT 放在数组变量gdt_table 中
  • 每个段的逻辑地址空间范围为0~4GB,每个段的基地址为0,偏移量就是线性地址,我们以后所提到的逻辑地址(或虚拟地址)和线性地址指的也就是同一地址
  • 把段分为两种:用户态(RPL=3)的段和内核态(RPL=0)的段
    • 描述符投影寄存器的内容很少发生变化,只在进程从用户态切换到内核态或者反之时才发生变化
    • 用户段和内核段的区别在其RPL 不同,因此内核根本无需访问描述符投影寄存器,当然也无需访问GDT,而仅从段寄存器的最低两位就可以获取RPL 的信息
  • Linux 的进程没有使用LDT,每个CPU 仅使用一个TSS(任务状态段)

分页机制

  • 线性 -> 物理地址

  • CR0中的PG位启用

  • 1:开启

  • 0:禁止分页机制

  • 每一页4K大小,4K对齐 --> 线性地址的低12 位经过分页机制直接地作为物理地址的低12 位使用

  • 页被标记为无效

  • 是线性地址是操作系统不支持的地址:程序因产生了无效地址而必须被终止

  • 在虚拟存储器系统中,线性地址对应的页存储在磁盘上,而不是存储在物理存储器中:该无效的地址实际上是请求操作系统的虚拟存储管理系统,把存放在磁盘上的页传送到物理存储器中,使该页能被程序所访问

无效页通常是与虚拟存储系统相联系,这样的无效页通常被称为未驻留页未驻留页是程序可访问的页,但它不在主存储器中。对这样的页进行访问,形式上是发生异常,实际上是通过异常进行缺页处理

  • 分页机构

  • 两级页表结构:对线性地址高20位的线性-物理地址转换分为两部分完成,每一步使用其中的10位

  • 页目录:页目录项

  • 页面项

  • 地址转换

  • 扩展分页

  • TLB

  • Linux中的分页机制