这篇文章是大量基于网络资源的学习笔记,但由于所参考的即是转载过的版本(且博客作者未注明转载源,在几经寻找仍未果的情况下,仍然无法找到真实出处,特此注明,如作者见到此文,请您联系我,我将注明出处)
本文着重从开发者的角度谈谈对内存管理的理解。遵循”理论来源于实践”的教条,我们不必一下子就钻入源码,那样容易迷失,所以本文从外到内(先从用户编程的范畴)来观察进程如何使用内存,等到大家有了直观的认识后,再深入到内核去学习内存如何被管理等理论知识。最后再通过一个实例融会贯通。
Linux 逻辑地址-线性地址-物理地址
- 逻辑地址:机器语言中出现的内存地址,都是逻辑地址。逻辑地址是相对于段的偏移地址
- 线性地址:逻辑地址加上段的基地址,就构成了线性地址。在Linux中,逻辑地址==线性地址,因为Linux所有的段(代码段、数据段、内核代码段、内核数据段)的线性地址都是从 0x00000000 开始,长度为 4G,这样, 线性地址 = 逻辑地址+0x00000000
- 物理地址:cpu与总线寻址的真实地址,线性地址到物理地址的转化要通过分页机制,具体的说,就是通过页表
进程与内存
进程对应的内存空间中包含5种不同的数据段
- 代码段:存放可执行文件的操作指令
- 数据段:可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量
- BSS段:程序中未初始化的全局变量,在内存中 bss 段全部置零
- 堆:存放被程序动态分配的内存段,大小不固定可扩展或缩减
- 栈:程序零食创建的局部变量,也就是函数 “{}” 中定义的变量
进程如何组织这些区域
从用户向内核看,所使用的内存表现形式依次会经历 “逻辑地址”–”线性地址”–”物理地址” 几种形式。
进程内存空间
Linux操作系统采用虚拟内存管理技术,使得每个进程都有各自互不相干的进程地址空间,该空间是大小为 4G 的线性虚拟空间,用户所看到的都是该虚拟地址,无法看到实际的物理内存地址。这样一来可以保护操作系统,二来用户程序可使用比实际物理内存更大的地址空间