日期:2014-05-16  浏览次数:20659 次

linux内存管理概述

Linux中的地址空间(一)
有这么一系列的问题,是否在困扰着你:用户程序编译连接形成的地址空间在什么范围内?内核编译后地址空间在什么范围内?要对外设进行访问,I/O的地址空间又是什么样的?
先回答第一个问题。Linux最常见的可执行文件格式为elf(Executable and Linkable Format)。在elf格式的可执行代码中,ld总是从0×8000000开始安排程序的“代码段”,对每个程序都是这样。至于程序执行时在物理内存中的实际地址,则由内核为其建立内存映射时临时分配,具体地址取决于当时所分配的物理内存页面。
我们可以用Linux的实用程序objdump对你的程序进行反汇编,从而知晓其地址范围。
例如:假定我们有一个简单的C程序Hello.c
? # include <stdio.h>
? greeting ( )? {
????????????? printf(“Hello,world!\n”);
? }
? main()?? {
???????? greeting();
?}
之所以把这样简单的程序写成两个函数,是为了说明指令的转移过程。我们用gcc和ld对其进行编译和连接,得到可执行代码hello。然后,用Linux的实用程序objdump对其进行反汇编:
$objdump –d hello
得到的主要片段为:
08048568 <greeting>:
?? 8048568:???? pushl? %ebp
?? 8048569:???? movl? %esp, %ebp
?? 804856b:???? pushl? $0×809404
?? 8048570:???? call??? 8048474? <_init+0×84>
?? 8048575:???? addl?? $0×4, %esp
?? 8048578:???? leave
?? 8048579:???? ret
?? 804857a:???? movl? %esi, %esi
?? 0804857c <main>:
?? 804857c:???? pushl? %ebp
?? 804857d:???? movl? %esp, %ebp
?? 804857f:???? call??? 8048568? <greeting>
?? 8048584:???? leave
?? 8048585:???? ret
?? 8048586:???? nop
?? 8048587:???? nop

其中,像08048568这样的地址,就是我们常说的虚地址(这个地址实实在在的存在,只不过因为物理地址的存在,显得它是“虚”的罢了)。

虚拟内存、内核空间和用户空间

?? Linux虚