Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2307980
  • 博文数量: 395
  • 博客积分: 10994
  • 博客等级: 上将
  • 技术积分: 5586
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-17 19:49
文章存档

2014年(1)

2013年(10)

2012年(74)

2011年(303)

2010年(7)

分类: 嵌入式

2011-05-06 09:15:21

转:http://hi.baidu.com/spiderjun/blog/item/fe529b8b5bd4b7779e2fb43b.html  
再论逻辑地址,线性地址和物理地址
2009-04-29 14:25
        前段时间在看操作系统内存部分原理的时候,见到了很多对各种地址的不同解释。呵呵,真是教科书不一样,解释也是千差万别。真是可怜了我这种将教科书视为神明的人了(曾经)!Andrew S. Tanenbaum在自己的《现代操作系统》中并没有给出明确的定义(或者是我太大意遗漏了?)。这就是高人的方法,既然是只可意会不可言传的东西,那么我就不给你做个定义。况且计算机软件相关的东西,做定义真的是远远没有作陈述来的精妙。无怪乎导师曾说definition已经行不通了,计算机科学里描述事物需要的是statement!
        最后声明一下,我在网上找到很多“高人”写的关于地址的概念的解释,很多都是错误的。希望大家有自己的判断力,不要听风就是雨。正确的理解是潜藏在操作系统源码中。废话说到这里,进入正题。我下面的解释是正解:

逻辑地址:

        如果是程序员,那么逻辑地址对你来说应该是轻而易举就可以理解的。我们在写C代码的时候经常说我们定义的结构体首地址的偏移量,函数的入口偏移量,数组首地址等等。当我们在考究这些概念的时候,其实是相对于你这个程序而言的。并不是对于整个操作系统而言的。也就是说,逻辑地址是相对于你所编译运行的具体的程序(或者叫进程吧,事实上在运行时就是当作一个进程来执行的)而言。你的编译好的程序的入口地址可以看作是首地址,而逻辑地址我们通常可以认为是在这个程序中,编译器为我们分配好的相对于这个首地址的偏移,或者说以这个首地址为起点的一个相对的地址值。
        当我们双击一个可执行程序时,就是给操作系统提供了这个程序运行的入口地址。之后shell把可执行文件的地址传入内核。进入内核后,会fork一个新的进程出来,新的进程首先分配相应的内存区域。这里会碰到一个著名的概念叫做Copy On Write,即写时复制技术。这里不详细讲述,总之新的进程在fork出来之后,新的进程也就获得了整个的PCB结构,继而会调用exec函数转而去将磁盘中的代码加载到内存区域中。这时候,进程的PCB就被加入到可执行进程的队列中,当CPU调度到这个进程的时候就真正的执行了。
   我们大可以把程序运行的入口地址理解为逻辑地址的起始地址,也就是说,一个程序的开始的地址。以及以后用到的程序的相关数据或者代码相对于这个起始地址的位置(这是由编译器事先安排好的),就构成了我们所说的逻辑地址。逻辑地址就是相对于一个具体的程序(事实上是一个进程,即程序真正被运行时的相对地址)而言的。尽管我们这样理解可能有一些细节上的偏差,但是比起网上一些含糊其辞,让人不知所云的描述要好得多,实用得多,等到自己对这个地址有更加深刻的理解的时候,再对上面的理解进行一些补充或者纠正。
   总之一句话,逻辑地址是相对于应用程序而言的。
线性地址:
   我们知道每台计算机有一个CPU(我们从单CPU来说吧。多CPU的情况应该是雷同的),最终所有的指令操作或者数据等等的运算都得由这个CPU来进行,而与CPU相关的寄存器就是暂存一些相关信息的存储记忆设备。因此,从CPU的角度出发的话,我们可以将计算机的相关设备或者部件简单分为两类:一是数据或指令存储记忆设备(如寄存器,内存等等),一种是数据或指令通路(如地址线,数据线等等)。线性地址的本质就是“CPU所看到的地址”。如果我们追根溯源,就会发现线性地址的就是伴随着Intel的X86体系结构的发展而产生的。当32位CPU出现的时候,它的可寻址范围达到4GB,而相对于内存大小来说,这是一个相当巨大的数字,我们也一般不会用到这么大的内存。那么这个时候CPU可见的4GB空间和内存的实际容量产生了差距。而线性地址就是用于描述CPU可见的这4GB空间。我们知道在多进程操作系统中,每个进程拥有独立的地址空间,拥有独立的资源。但对于某一个特定的时刻,只有一个进程运行于CPU之上。此时,CPU看到的就是这个进程所占用的4GB空间,就是这个线性地址。而CPU所做的操作,也是针对这个线性空间而言的。之所以叫线性空间,大概是因为人们觉得这样一个连续的空间排列成一线更加容易理解吧。其实就是CPU的可寻址范围。
   对linux而言,CPU将4GB划分为两个部分,0-3GB为用户空间(也可以叫核外空间),3-4GB为内核空间(也可以叫核内空间)。操作系统相关的代码,即内核部分的代码数据都会映射到内核空间,而用户进程则会映射到用户空间。至于系统是如何将线性地址转换到实际的物理内存上,那是另外的话题了。网上到处可以找到相关文章,我不在此啰嗦。对于X86,无外乎段式管理和页式管理。
   总之一句话,线性地址是相对于CPU而言的。
物理地址:
   似乎没什么可说的。无非就是内存中的实际地址编号。一个字节编一个号。如果不明白,那把你的内存条拔下来,用放大镜仔细看看,也许就可以看到这些编号了^_^!
   逻辑地址到线性地址的转换,以及线性地址到物理地址的转换,网上有铺天盖地的资料,百度一下就可以了。

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