Linux 内存地址与分段机制

Linux 内存地址与分段机制

基于80x86

逻辑地址

指定一个操作数或一条指令的地址,这种寻址方式,在80x86分段模式下表现的尤为得体,在Windows里二进制可执行文件会分为若干段。每一个逻辑地址都由一个段和偏移组成,偏移量指定了从段开始的地方到实际地址的距离。

线性地址

也可以叫做虚拟地址,是一个32位整数,最高可以表示到4294967296个内存单元。通常用16进制表示,值的范围0x00000000到0xFFFFFFFF

物理地址

用于内存芯片级内存单元寻址。他们从微处理器的地址引脚发送到内存总线上的电信号对应。物理地址由32位或36位unsigned int 表示

内存管理单元(MMU)通过一种称为分段单元的硬件电路,把一个逻辑地址转换为线性地址,接着,第二个称之为分页单元的硬件电路把线性地址转换为物理地址。

1536740000646

在多处理器系统中,所有 CPU都共享同一内存,这意味着 RAM芯片可以由独立的 CPU并发地访问。因为在RAM芯片上的读或写操作必须串行地执行,因此一种所谓内存仲裁器的硬件电路插在总线和每个 RAM芯片之间,其作用是如果某个 RAM芯片空闲,就准予一个 CPU访问,如果该芯片忙于为另一个处理器提出的请求服务,就延迟这个 CPU的访问 。即使在单处理器上h也使用内存仲裁器,因为单处理器系统中包含一个叫做 DMA控制器的特殊处理器,在多处理器系统的情况下,因为仲裁器有多个输入端口,所以其结构更加复杂,例如,双Pentium在每个芯片的入口维持一个两端口仲裁器,并在试图使用公用总线前请求两个CPU交换同步信息.从编程观点看,因为仲栽器由硬件电路管理,因此它是隐藏的。

系统分段

一个逻辑地址由两部分组成:一个段标识符和一个指定段内先对地址的偏移量。段标识符是一个16位长的字段,称为段描述符。而偏移量是一个32位长的字段。

1536740109090

处理器提供6个段寄存器,保存了段选择符,分别是:cs ss ds es fs gs,6个段寄存器。

cs 代码段寄存器

ss 栈段寄存器

ds 数据段寄存器

cs 寄存器中,含有一个两位字段,用以指明CPU的当前CPL(Current Privilege Level),0代表R0级别,1代表R3级别。分别称为,内核态和用户态。

段描述符

每个段由一个8字节的段描述符表示,他描述了段的属性,段描述符放在GDT(Global Descriptor Table)或LDT(Local Description Table)中。

一般来说只定义一个GDT,而每个进程除了存放在GDT中的段之外如果还有附加的段,就可以有自己的LDT。GDT在主存中的地址和大小存放在gdtr控制寄存器中,当前正在被使用的LDT地址和大小放在ldtr寄存器中。

段描述符格式

1536740043063

段描述符字段

字段 描述
BASE 包含段的首字节的线性地址
G 粒度标志:如果该位清0,、则段大小以字节为单位,否则以4096字节的倍数计算
Limit 存放段中最后一个内存单元的偏移量,从而决定段的长度,如果G被置为0,则一个段的大小在1个字节1 MB之间变化。否則,将在4 KB到 4 GB 之间变化
S 系统标志:如果它被清0,则这是一个系统段,存储诸如 LDT这种关鍵的数据结构,否則它是一个普通的代码段或数据段。
Type 描述了段的类型特征和它的存取权限。
DPL 描述符特权级字段,用于限制对这个段的存取 。 它表示为访问这个段而要求的 CPU最小的优先级 。因此, DPL设为0的段只能当 CPL设为0时(即在内核态)才垃可访问的,而 DPL设为3的段对任何CPL都是可访问的。
P Segment-Present标志:等于0表示段当前不在主存中, Linux总是把这个标志(第47位)设为1。因为它从来不把整个段交换到磁盘上去。
D 或 B 称 为 D成 B的标志,取决于是代码段还是数据段 ,D或B的含义在两种情况下稍有所区别,但是如果段偏移量的地址是32位长,就基本上把它置为 1.如果这个偏移置是16位长,它被清0。
AVL 被Linux忽略。

代码段描述符

​ 表示这个段代表一个代码段,他可以放在GDT或LDT中,S标志位为1。

数据段描述符

​ 表示这个段代表一个数据段,他可以放在GDT或LDT中,S标志位为1。

任务状态段描述符(TSSD)

​ 表示这个段描述符代表一个任务状态段(Task State Segment)TSS,也就是说这个段用于保存处理器寄存器的内容它只能出现在GDT中。根据相应的进程是否正在CPU上运行,Type字段的值分别为11或9.这个描述符的S标志置0。

局部描述符表描述符(LDTD)

​ 表示这个段描述符代表一个包含LDT的段,它只出现在GDT中。相应的Type字段的值 为2,S标志置为0。

1571159997314

Author: BarretGuy
Link: https://basicbit.cn/2016/03/12/2016-03-14-Linux内存地址/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.