《understanding the linux kernel》笔记: 2. Memory Addressing(内存地址)

版权声明:本文为博主原创文章,转载请注明出处,欢迎转载。 https://blog.csdn.net/Dylan_Frank/article/details/82558981

remark:《understanding the linux kernel》笔记第二篇,对应原书第二章。

x86 内存地址

x86有三种内存地址:

  1. logical Address: segment: offset(48bit),段基址+ 偏移
  2. linear Address: 0x00000000-0xffffffff

    前两个都是虚拟地址,不是实地址

  3. Physical address 真实的内存单元的地址,32-bit或者36-bit

MMU (the Memory Management Unit) 内存管理单元

MMU 是一个硬件,它主要做地址翻译:

这里写图片描述

Segmentation in Hardware 硬件分段机制

这里写图片描述

段选择子是16bit的段寄存器,分成3部分:

  • RPL(0-1): 请求特权级(request privilege level)与段访问权限有关
  • TI(2): table indicator (0在GDT中,否则在LDT中)
  • Index(3-15): 段索引

有6个段寄存器:cs(code segment),ss(stack seg),ds(data seg),es,fs,gs

segmentation descriptor 段描述符

每个段描述符占8-bytes

这里写图片描述

上面所列出来的每个field 都在原书上有标明含义,见Table 2-1

这里写图片描述
这里写图片描述

还有两个段描述符表,GDT(全局段描述符表)总共256( 2 8 )项被所有进程共享,LDT局部段描述表,他们的起始地址存在 gdtr和ldtr 寄存器中

Fast Access to Segment Descriptors

这是加快地址翻译用的,其实就是加了一个缓存
这里写图片描述

右边的不可编程寄存器(nonprogramable register) 缓存了左边的翻译地址,使得不必每次都到内存中去取段描述符

segmentation unit

逻辑地址转化为物理地址的流程:

这里写图片描述

由于不可编程寄存器(见上图)的存在,前两步仅在段描述符改变是才会访问内存

segmentation in Linux linux中的分段机制

linux 将段机制给弱化了,主要出于以下两个原因:

  1. 内存管理更加简单是,如果他们共享同样的线性地址空间
  2. 适应不同的体系结构

这是linux主要的几个段

这里写图片描述

linux 中所有进程共享逻辑地址空间(0x0-0xffffffff)

GDT & LDT

GDT没啥好说的(这个表可以再内核代码中找到),ldt linux中设计了一个default_ldt 被most process 使用,如果进程要用自己的ldt 可以用modify_ldt创建

Paging in Hardware

控制寄存器 cr0 中有一个 PG 位,当PG=0 时,线性地址就是物理地址,页机制没有开启,PG=1 页机制被开启

这里写图片描述

常规的32-bit的页管理,分了2级页表,由于页表在内存中,每次访问都需要3次内存访问才能访问到物理地址,不过由于硬件缓冲 TLB我们可以加快页的访问.

Paging in Linux

linux 可以用4级页表,取决于cpu的体系结构

这一节我并没有理解多少内容,号多细节,涉及源码我都跳了,过去,接下来说一说,我所理解的那一部分内容

物理内存布局

还记的系统是怎么开机的吗?(参见《understanding the linux kernel》笔记: 1. linux开机发生了什么?)最后一步是内核初始化,这里内核需要建立物理映射,标记哪些是可用的内存地址,哪些是不可以用的。内核代码从第2M 开始,即 0x100000,第一M 通常是一些系统参数和BIOS以及体系结构相关的东西,出于为了让内核代码连续的考虑将内核代码放在 0x100000开始出,前3M布局如下图

这里写图片描述

进程页表(process page table,PPT)

这里写图片描述

猜你喜欢

转载自blog.csdn.net/Dylan_Frank/article/details/82558981