虚拟地址、物理地址等等与进程之间关系有一些乱,在这里捋一下
对于一个进程,其空间分布:
0~3G从低地址到高地址:
程序段(text):程序代码在内存中的映射,存放函数体的二进制代码
只读数据段rodata
初始化过的数据:在程序运行初已经对变量进行初始化的数据
未初始化过的数据(BSS):在程序运行初未对变量进行初始化的数据
堆 (Heap):存储动态内存分配,需要程序员手工分配,手工释放.注意它与数据结构中的堆是两回事,分配方式类似于链表。
栈 (Stack):存储局部、临时变量,函数调用时,存储函数的返回指针,用于控制函数的调用和返回。在程序块开始时自动分配内存,结束时自动释放内存,其操作方式类似于数据结构中的栈。
32位Linux的虚拟地址空间范围:0~4G
分为:内核空间(3~4G)和用户空间(0~3G)
内核空间在页表中拥有较高的特权级(ring2或以下),用户空间较低,因此只要用户态的程序试图访问这些页,就会导致一个页错误(page fault)(用户空间权限低,内核空间权限相对较高)。在Linux中,内核空间是持续存在的,并且在所有进程中都映射到同样的物理内存(借助MMU),内核代码和数据总是可寻址的,随时准备处理中断和系统调用。与之相反,用户模式地址空间的映射随着进程切换的发生而不断的变化。
在栈的下方是内存映射段,内核将文件的内容直接映射到内存。任何应用程序都可以通过Linux的mmap()系统调用或者Windows的CreateFileMapping()/MapViewOfFile()请求这种映射。内存映射是一种方便高效的文件I/O方式,所以它被用来加载动态库。
为什么要有虚拟地址:
虚拟内存机制 - 迪米特 - 博客园 (cnblogs.com)
分页机制