码迷,mamicode.com
首页 > 其他好文 > 详细

Kernel那些事儿之内存管理(10) --- 映射(上)

时间:2015-07-31 18:42:57      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:内存管理   linux kernel   

前面花了好多时间讲了内存管理中 node, zone, page frame, buddy system等。这些都是物理地址空间中的概念。然而,对于一个进程来说,它看到的却是完全不同的地址空间。


我们接下来就来看看这些地址空间,以及它们之间的映射。


1.内存地址

在内存管理中,会涉及到三种内存地址。

  1. 逻辑地址:程序的机器语言指令里,指定一条指令或是一个操作数的地址时,所使用的实际上都是逻辑地址。一个逻辑地址由两部分组成:段选择符和段偏移值。

  2. 线性地址:逻辑地址经过分段映射后,得到的就是线性地址。

  3. 物理地址:访问内存条上的内存单元时所使用的地址。CPU会把该地址送往地址总线来读/写某一内存单元。


逻辑地址到物理地址的转换是由MMU (Memory Management Unit)来完成的:分段单元把逻辑地址转换为线性地址,分页单元把线性地址转换为物理地址。


技术分享


2.分段

系统中每个段都有一个对应的段描述符。段描述符中包含了该段的详细信息,比如:段的起始地址,段的长度,段的类型,段的权限等等。

系统中所有的段描述符都集中放在了两个table里:GDT (Global Descriptor Table) 或是 LDT (Local Descriptor Table)。这两个表的线性地址分别保存在寄存器 GDTR 和 LDTR 中。


一个逻辑地址由段选择符和段内偏移值组成。其中,段选择符格式如下:

技术分享


TI:Table Indicator,指定了该段存在于GDT中(TI = 0)还是LDT中(TI = 1)。

index:指定了该段在GDT/LDT中的索引。

RPL:Requestor Privilege Level,与该段的权限相关。


系统提供了不同的段寄存器来存放段选择符:CS, SS, DS, ES, FS, GS. 其中,CS专门来放代码段的段选择符,DS专门来放数据段的段选择符,SS专门来放栈的段选择符。

其中,CS段寄存器中的RPL,代表了CPU当前的运行level。Linux只是用了两个level:0(内核态)和 3(用户态)。


逻辑地址经过分段单元转换成线性地址的过程,可以用下面的图来说明:

技术分享


Linux简化了分段逻辑:所有运行在用户态的进程,都使用同一个代码/数据段,即用户态代码/数据段;同样的,所有运行在内核态的进程,都使用同一个代码/数据段,即内核态代码/数据段。

这四个段的段选择符由四个宏来定义:__USER_CS,__USER_DS,__KERNEL_CS,__KERNEL_DS。


而且,这四个段的起始地址都为0x0。这样带来一个好处:逻辑地址中的段偏移值总是和对应的线性地址相等。所以,逻辑地址空间到线性地址空间的映射,是非常简单的。


3.分页

既然Linux中所有的进程都使用相同的线性地址空间,那么将这些进程分隔开来的重任就要由分页来完成了。

分页机制非常简单,一张图就可以讲清楚了:

技术分享


不同的进程,虽然使用相同的线性地址空间,但是会使用不同的页表,因此实际上使用的物理地址是不同的。


不过,线性地址空间到物理地址空间的映射,却并没有这么简单,是我们接下来的重点。


本文出自 “内核部落格” 博客,请务必保留此出处http://richardguo.blog.51cto.com/9343720/1680683

Kernel那些事儿之内存管理(10) --- 映射(上)

标签:内存管理   linux kernel   

原文地址:http://richardguo.blog.51cto.com/9343720/1680683

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!