Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226281
  • 博文数量: 88
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 555
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-03 13:08
个人简介

失意高调,得意低调

文章分类

全部博文(88)

文章存档

2021年(3)

2020年(2)

2018年(2)

2017年(3)

2016年(6)

2015年(19)

2014年(32)

2013年(21)

我的朋友

分类: LINUX

2013-09-05 16:55:44

原文地址:Linux 内存管理 作者:formycuteboy

内存管理子系统:

内存 是 Linux 内核所管理的最重要的资源之一;

内存管理子系统 是操作系统中最重要的部分之一.

对于立志从事内核开发的工程师来说,熟悉Linux 的内存管理系统非常重要.


地址类型:

1,物理地址:

物理地址是指出现在 CPU 地址总线上的 寻址物理内存的地址信号

地址变换的最终结果


2,线性地址 ( 虚拟地址 ):

线性地址又名 虚拟地址,在 32 位 CPU 架构下,可以表示 4G 的地址空间,

用 16进制 表示就是 0x00000000 到 0xFFFFFFFF.


3,逻辑地址:

程序代码经过编译后,在汇编程序中使用的地址;


地址转换:

CPU 要将一个 逻辑地址   转换为   物理地址

需要两步:

首先 CPU 利用 段式内存管理 单元,将逻辑地址 转换成线性地址

再利用 页式内存管理 单元,把 线性地址 最终转换为 物理地址.


段式管理:

十六 位 CPU :

16 位 CPU 内部拥有 20 位的地址线,它的寻址范围就是 2 的 20 次方,也就是 1M 的内存空间.

但是 16 位 CPU 用于存放地址 寄存器 ( IP , SP ......)只有 16位,因此只能访问 65536 个存储单元,64K.


为了能够访问 1M 的内存空间,CPU 就采用了 内存分段 的管理模式,并在 CPU 内部加入了段寄存器.

16 位 CPU 把 1M 内存空间分为若干个逻辑段,

每个逻辑段的要求如下:

1,逻辑段的起始地址 ( 段地址 ) 必须是 16 的倍数,即 最后 4 个 二进制位必须全为 0.

2,逻辑段 的最大容量为 64 K.


物理地址的形成方式:

由于段地址 必须是 16 的倍数,所以值的一般形式 为 XXXX0H , 即 前 16 位 二进制是变化的,后 4 位 是固定的.

鉴于段地址的这种特性,可以只保存前 16 位 二进制来保存整个段基地址,

所以每次使用时要用段寄存器左移补 4 个 0  ( 乘以16 ) ,来得到实际的段地址.


在确定了某个存储单元所属的段后,只是知道了该存储单元所属的范围 ( 段地址 -> 段地址 + 65536 )

如果想确定 该内存单元的具体位置,还必须知道 该单元在内存的偏移,有了段地址偏移量

就可以唯一的 确定内存单元在 存储器中的具体位置.

逻辑地址 = 段基地址 + 段内偏移量

逻辑地址 得到 物理地址 的公式为:

PA = 段寄存器的值 * 16 + 逻辑地址


段寄存器是为了对内存进行分段管理而增加的,

16位 CPU 有四个段寄存器,


程序可同时访问四个不同含义的段:

1,CS + IP :

用于代码段的访问, CS 指向 存放程序的段基址, IP 指向下条要执行的指令在 CS 段的偏移量,

用这两个 寄存器就可以得到一个内存物理地址,该地址存放着一条要执行的指令.


2,SS + SP :

用于堆栈段的访问, SS 指向栈顶,

 可以通过 SS 和 SP 两个寄存器直接访问栈顶单元的内存物理位置.


3,DS + BX :

用于数据的访问. DS 中的值左移四位得到数据段起始地址,再加上 BX 中的偏移量,

得到一个存储单元 的物理地址.


4,ES + BX :

用于附加段的访问. ES 中的值在 左移四位 得到 附加段起始地址,再加上 BX 中的偏移量,

得到一个存储单元的 物理地址.


三十二 位 CPU:

32 位 PC 的内存管理仍然采用 " 分段 " 的管理模式,逻辑地址同样由段地址和偏移量两部分组成,

32 位 PC 的内存管理和 16 位 PC 的内存管理有 相同 和不同之处,因为 32位 PC 采用了两种不同的工作模式:

实模式 和 保护模式.


实模式:

在实模式下, 32 位 CPU 的内存管理 与 16 位 CPU 是一致的.


保护模式:

段基地址长达 32 位,每个 段的最大容量可达 4G ,段寄存器的值是段地址的 “ 选择器 ” ( Selector ),

用该 “选择器” 从内存中得到一个 32 位的段地址,存储单元的物理地址就是 该段地址加上 段内偏移量,

这与 32 位 CPU 的物理地址计算方式完全不同.


三十二  位 CPU 内有 6 个段寄存器

其值在不同的模式下具有不同的意义:

1,在实模式下:

段寄存器的值 * 16 就是 段地址.

2,在保护模式下:

段寄存器的值是一个选择器,间接指出一个 32 位 的段地址.


分页管理:

从管理 和效率 的角度出发,线性地址 被分为固定长度的组,称为 页 ( page )

例如: 32 位的机器,线性地址最大可为 4G ,如果用 4K 为一个页 来划分,

这样整个线性地址就被划分为 2 的 20 次方个页.


另一类 “ 页 ” ,称之为 物理页,或者是 页框页帧.

分页单元把所有的 物理内存 也划分为固定的长度的管理单位,

它的长度一般与线性地址页是相同的.






Linux 内存管理:

Linux 内核 的设计并没有全部采用 Intel 所提供的段机制,

仅仅是 有限度的 使用了分段机制,这不仅简化了 Linux 内核的设计,

而且 为把 Linux 移植到其他平台创造了条件,因为 很多的 RISC 处理器并不支持段机制.


所有段的基地址均为0


由此可以得出,每个段的逻辑地址空间范围 为 0 - 4 GB,

因为每个段的基地址为 0 ,因此,逻辑地址 与 线性地址保持一致 ( 即 逻辑地址 的偏移量 字段的值 与 线性地址的值 总是 相同的 ),

在 Linux 中所提到的 逻辑地址 和线性地址 ( 虚拟地址 ),可以认为是 一致的.

看来 , Linux 巧妙的把 段机制给绕过去了,而 完全利用了分页机制.


Linux 页式管理:




阅读(522) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~