|
发表于 2003-10-9 21:04:51
|
显示全部楼层
你好,你问的很好,我也不是特别的懂,现在我就我的理解说一下,请大家多指教:这里只讨论linuxi386系列:
我们先看下面一段反汇编代码这是我随便截取的,旨在说明各种地址的关系)
0804835c <main>:
804835c: 55 push %ebp
804835d: 89 e5 mov %esp,%ebp
804835f: 83 ec 08 sub $0x8,%esp
8048362: 83 e4 f0 and $0xfffffff0,%esp
8048365: b8 00 00 00 00 mov $0x0,%eax
804836a: 29 c4 sub %eax,%esp
804836c: e8 0b ff ff ff call 804827c <_init+0x28>
,看到最左面的地址了吗?那是gcc编译的时候给的,gcc再ld(估计是链接还是什么的)的时候总是从0x8000000开始的,至于0x8000000就可以理解成为虚拟地址了,也可以看成是逻辑地址(逻辑地址是这么理解的吗?是不是逻辑地址是那些段式管理的os里面的概念呢?)了.
楼上的第一句 "在linux中针对i386架构的cpu所作的地址映射实际上是使线性地址和逻辑地址相等" 这句话很含糊,i386系列本身就是要将逻辑地址通过段式管理来映射到最终的物理地址,而linux是页式管理,根本就没有段式管理的必要,但是因为linux跑在i386上面自然要遵从段式管理的需要,因为这是硬件上的要求,可是linux绕了一个弯子,让段式管理的段式映射有了等于 没有,而楼上你的"因此cpu可以通过ecs寄存器中的段地址(也就是线性地址)再到pgd\pte中找到相应的物理地址。 "这句话完全将段式管理和页式管理搞混掉了.
我们看到上面的程序的最后一行就是对804827c(这个是虚拟地址,可以理解成逻辑地址吗?)寻址,接着进行段式管理的地址转换(具体看qjfx)转换的结果还是804827c,这就是线性地址,然后在根据已经设置好的的pgd/pte进行最终的线性地址到物理地址的映射.
你的第一个问题,编译之后的确是虚拟地址,但不是线性地址,要先转个弯子(形式上的进行段式管理一下),虽然二者的地址是一样的.
第二个问题,编译器确切根据什么给地址我不清楚,但是qjfx上p35上面提到用户程序的起始地址是在0x8000000上开始的,此时可以不用考虑实际的物理地址怎样.要不然怎么叫虚拟地址呢?
最后一个问题"既然分配了线性地址,就说明在系统空间中分配给进程的相应物
理空间在编译时就已经确定了",在我们编译程序的时候不要忘了我们是在操作系统上的,os做的工作就是为我们分配相应的物理内存和相应的pgd/pte映射,如果该页面已被使用,那os是不会分配给用户的.
不知道上面的解释还有什么疑问,本人水平有限,请多指教 |
|