美文网首页
ULK之一内存寻址之分段

ULK之一内存寻址之分段

作者: 1哥 | 来源:发表于2021-11-13 18:32 被阅读0次

1.背景

有了前面主存的分段的设计原理的背景知识,对于这里提到的分段和分页会更好理解。
X86处理器有三种不同内存地址:

  • 逻辑地址
  • 线性地址
  • 物理地址

X86 地址转换

image.png

MMU(内存管理单元)

  • 一种硬件,包含分段管理单元电路和分页管理单元电路
  • 通过分段管理单元电路,负责将CPU 产生的逻辑地址转换成实际的物理内存地址
  • 通过分页管理单元电路,负责将线性地址转换成物理地址。

2.分段的实现

image.png
分段概念
  • 将整个进程地址空间划分成单独的逻辑地址空间
    代码段,数据段,堆段,栈段

分段的实现

  • 虚拟地址:{段号,段内偏移}
  • 段的表示
    段基地址 + 段长度
    检查访问的偏移与段长度,提供保护
  • 段描述符表
    映射段号到段的基地址和段长度

分段在80x86的实现

  • 逻辑地址表示:{段描述符, 段偏移}
  • 段标识符(段选择符): 16 bit


    image.png
字段 位数 用途
index 13 bit 段选择
TI 1bit GDT or LDT 指示器
RPL 2bit 特权级别选择
  • 段描述符


    image.png
image.png
  • 段表
    1)段描述符要么存在全局描述符表(GDT),要么局部述符表(LDT)
    2)存放在内存中的地址寄存器:gdtr or ldtr

  • 转换过程如图
    1)检查段选择符的TI,确定段描述符在哪个描述符表(LDT or GDT)
    2)计算段描述符的地址: 据1)确定的位置,计算地址=gdt or ldtr 的值 + index * 8;
    3)得到线性地址:线性地址 = 2)确定的段描述符的地址的base + offset;


    image.png
  • 处于性能考虑

    • 段选择符寄存器
      1)为了更容易更快速获取段选择符
      2)六个:cs, ds, ss, es, fs, gs
    • 不可编程的寄存器
      1)6个寄存器,对应6个段描述符
      2)每次fork和上下文切换时,设置段描述符寄存器到对应的不可编程CPU寄存器中,此时逻辑地址转换需要访问GDT或者LDT
      3)后续地址转换,逻辑地址转换不需访问GDT或者LDT,直接引用包含段描述符的CPU寄存器的值
      image.png

3.分段在Linux 中的实现

3.1 段结构

  • 2.6 的Linux 只在x86 下才使用分段
  • 段描述符
    1)所有段地址从0x0 开始,Linux 下,逻辑地址和虚拟地址相同
    2)用户进程段选择符,通过__USER_CS、__USER_DS
    3)内核进程段选择符,通过__KERNEL_CS、__KERNEL_DS


    image.png
  • CPL(CPU当前特权级别)
    1)由cs的段选择符的RPL 确定
    2)当CPL 改变时对于的段寄存器需要更新
    如CPL=3(用户 mode)时,ds必须包含用户数据段的段选择符
    如CPL=0(内核 mode)时,ds必须包含内核数据段的段选择符

3.2 GDT

  • 每个CPU 对应一个GDT
  • 所有GDT 存放在cpu_gdt_table里
  • 所有的GDT地址和大小被存放在 cpu_gdt_descr数组
  • 这些符号定义在 文件arch/i386/kernel/head.S.
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);

void __init cpu_init (void)
{
        //省略部分代码
       memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
              GDT_SIZE);
       cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
       cpu_gdt_descr[cpu].address =
           (unsigned long)&per_cpu(cpu_gdt_table, cpu);
        //省略部分代码
}
  • GDT layout
    18个 段描述符


    image.png

相关文章

  • ULK之一内存寻址之分段

    1.背景 有了前面主存[https://www.jianshu.com/p/93379229d2c1]的分段的设计...

  • Linux内存寻址——分页与分段

    物理地址与虚拟地址 物理地址,也叫实地址、二进制地址,它是在地址总线上,以电子形式存在的,使得数据总线可以访问主存...

  • Linux内存寻址之分段机制

    前言 最近在学习Linux内核,读到《深入理解Linux内核》的内存寻址一章。原本以为自己对分段分页机制已经理解了...

  • Linux内存寻址之分页机制

    在上一篇文章Linux内存寻址之分段机制中,我们了解逻辑地址通过分段机制转换为线性地址的过程。下面,我们就来看看更...

  • 寻址和分段

    三种地址 逻辑地址:包含再机器语言指令中用来指定一个操作数或一条指令的地址。这个寻址方式再80x86著名的分段结构...

  • 内存寻址

    1、寻址公式一:【立即数】 mov eax,dword ptr ds:[0x12FF5C] mov dword p...

  • [Redis] 一、介绍及NIO原理介绍

    常识 磁盘寻址:ms带宽:G/M 内存寻址:ns带宽:很大?秒>毫秒>微秒>纳秒 磁盘比内存在寻址慢10w倍I/O...

  • 1.redis介绍及NIO

    磁盘 1.寻址 ms级2.带宽 G/M 内存 1.寻址 ns2.带宽 很大磁盘寻址速度比内存慢10w倍 IO bu...

  • 内存读写-内存寻址

    DTDebug再介绍 左下角就是内存数据窗口。最下面是命令行窗口。我们可以输入命令查看某一块内存的数据db 0x0...

  • Linux 内存管理篇(2)内核初始化与内存管理启用

    前言 继内存寻址之后, 本篇开始介绍Linux内核地址空间初始化过程。 通过内存寻址篇我们知道, Linux 系统...

网友评论

      本文标题:ULK之一内存寻址之分段

      本文链接:https://www.haomeiwen.com/subject/qfrezltx.html