linux 内存管理之内存寻址

我发现人是一个懒惰的生物,总是不愿意去做一些对自己成长有好处的事,总是以工作忙,上班累为借口。所以成功的人总是占少数的,我也是,明明很早就知道写技术博客对自己知识框架的搭建有益,却总是因为各种理由无法提笔。有人说,种一棵树最好的时间是10年前,其次是现在,所以朋友们,加油吧。

今天开始写linux内核的东西,刚接触内核不久,看过很多博客和书籍,权当自己的笔记了。有人说,当你可以把一个知识给别人讲懂时,你自己也就懂了,所以,我想以教别人的口吻去描述这个知识点,以求自己也能深刻理解,文中参考了很多资料,并不是自己就能写出来的,我也记不太清就不列举了,但主线大概就是陈莉君老师翻译的《深入理解linux内核》吧,有兴趣的可以看看。
  
  废话不多说,今天我们开始说内存寻址(以x86为背景,其实arm系统也差不多,我们主要是想了解操作系统,平台只是承载)。内存寻址,顾名思义,处理器是如何找到数据和指令存储的地址的(物理地址),它是属于内存管理中最基础的部分,是操作系统设计的硬件基础之一。
  
一、Intel处理器的历史
先来看Intel处理器的发展历史,这对理解分段和分页机制是很重要的。
  1. 4位CPU时期:4004,这是一个4位的CPU,太弱了,以至于都不想对它有太多描述。
  2. 8位CPU时期:8080,这是一个8位CPU,它有一个主累加器(寄存器A)和6个次累加器(BCDEHL),由于没有分段的概念,内存的访问需要通过绝对地址,这可苦当年的程序员,需要对每个内存地址进行硬编码,写程序时还要看这个内存有没有人用啊,这样大大降低了当时软件编码的效率。
  3. 16位CPU时期:8086处理器,这是一款划时代的处理器,为什么这么说
呢?因为它引入了一个非常重要的机制:“段”,分段机制从这款芯片开始,一直延续到现在的处理器。我们接下来会说说它为什么引入这个段机制,又是怎么引入的。
  4. 保护模式时期:80286这款处理器把cpu的地址总线从8080的20位(为什么是20位后面会解释)增加到24位,并且引入“保护模式”,即访问内存时不能直接从段寄存器中获得段的起始地址,而是要经过额外的转换的检查。不过cpu是16位的,地址总线是24位的,是不是很奇怪,80286是有致命缺陷的,因此intel推出了80386,这个芯片就牛X了,直接变成32位的 CPU,使得寻址能力达到4GB。
  
  是不是有些凌乱了,我们一一解释一下。

二、什么是段 
   首先什么是“段”,段可以理解为一片连续的内存空间。什么意思呢?假如我们有4G的虚拟内存,那么随便从4G内存中抠出一段连续的内存空间,就可以称之为段。那么在8086时期,为什么要引入“段”,怎么引入的“段”呢?我们知道8086是16位的CPU,因此它的数据总线是16位,只能寻址2^16=64K内存空间,但是这款芯片的设计目标是寻址1M的内存空间,因此它的地址总线是20位的(2^20=1M)。如何设计呢?答案就是分段,为了支持分段,8086设置了4个段寄存器:CS, DS, SS, ES,分别对应代码段,数据段,堆栈段和其他段,每个段寄存器都是16位。我们编译的程序也是按照段存储的,指令代码放在一起,成为代码段,数据放在一起,成为数据段,每个段对应一块内存空间,这个内存空间是有首地址的,这个首地址就放在段寄存器中。下面有几个问题:
  
   如何找到指令呢?答案是通过段内偏移,段首地址+段内偏移=要访问的内存地址。段首地址放在段寄存器。
  
   那么偏移量放在哪里呢?就是大名鼎鼎的IP寄存器,我们经常听说它,它存放的是下一条指令的地址,其实这里面存放的就是偏移量。
  
   最后一个问题,怎么得到20位的地址?首先将16位的段寄存器向左移4位,然后加上16位的偏移量,不就得到20位的地址了么。这就是分段技术的关键。其实可以这样理解,我有16根数据总线,一共只能访问64k的地址空间,那我把1M的地址空间分成若干个64K的段,然后我就可以用16根数据总线去访问这个段的每个地址了。

三、保护模式是神马东西
  我们来回想一下处理器分段技术,段寄存器中存放的就是段首地址,因此物理内存对于cpu来讲是可见的,这是一件非常可怕的事情。试想一下,我一块内存就那么大个儿,如果我想运行多任务(多进程),会发生什么情况呢?显然多任务有可能会访问到同一块物理内存,导致程序出现意想不到的结果,因此,引入“保护模式”是必然的选择。
  
  保护模式保护啥?首先是保护操作系统,由于物理内存是不可见的,因此程序的出错不会造成操作系统的出错。其次,也是最重要的,保护进程的地址空间
在保护模式下,32条地址线都可以使用,可寻址范围达到4GB。其实在80386之后的CPU,既支持保护模式,也支持实模式(实模式就是只能使用20根地址线,访问1M内存空间,像上面介绍的8086,就只支持实模式),在CPU上电时,首先就是以实模式运行,只能使用20根地址线,访问1M内存,待加载操作系统模块后,就以保护模式运行。

那保护模式如何寻址呢?下一小节见分晓。

你可能感兴趣的:(linux内存管理,Linux内存管理之内存寻址)