1、内存管理架构图
分为用户空间,内核空间,硬件三个层面:
方便用户——段——虚拟内存
方便操作系统——页——物理内存
1、用户空间
应用程序malloc()
申请内存,free()
释放内存(是内存分配器ptmalloc
提供的接口),内存分配器ptmalloc
使用系统调用brk()
或者mmap()
向内核以页为单位申请内存,然后划分成小内存块分配给程序
2、内核空间
虚拟内存管理,负责把用户地址映射成虚拟地址,从进程的虚拟地址空间分配虚拟页
- sys_brk()用来扩大缩小堆,
- sys_mmap()用来内存映射区域分配虚拟页
- sys_munmap()用来释放虚拟页
页分配器负责分配物理页。
3、硬件
内存管理单元MMU,负责把虚拟地址转换成物理地址。
内存管理单元包含页表缓存TLB,保存最近使用过的页表映射
解决CPU以及内存处理速度不匹配问题,加了缓存
2、虚拟地址空间
虚拟地址空间的内部又被分为内核空间和用户空间
32 位系统的内核空间占用 1G,位于最高处,剩下的 3G 是用户空间。大小用TASK_SIZE
表示,即0X100000000
64位系统虚拟地址最大为48位,所以中间会有空缺。属于不规范地址,不允许使用
2.1 用户虚拟地址空间
包括:
(1) 代码段,包括代码和常量等。
(2) 数据段,包括全局变量等。
(3) 未初始化数据段,例如int赋值0等。
(4) 堆,包括动态分配的内存。
(5) 内存映射区域,把文件区间映射到虚拟地址空间。
(6) 栈,包括局部变量和函数调用。底部存放环境变量和参数字符串。
上图为传统布局:内存映射区域自底向上增长,起始地址是TASK_UNMAPPED_BASE+随机值
内核支持为内存映射区域、栈和堆选择随机的起始地址
可见,内存变化最大的区域从大到小排序是(1)堆(2)内存映射区域(3)栈
2.2内核地址空间布局
3、物理地址空间
虚拟地址到物理地址映射,由硬件自动完成,不过多赘述
4、内存映射
内存映射指在进程的虚拟地址空间创建一个映射,有两种
1、文件映射:就是磁盘中的数据通过文件系统映射到内存,再通过文件映射映射到虚拟空间.这样,用户就可以在用户空间通过 open ,read, write 等函数区操作文件内容.
2、匿名映射: 就是用户空间需要分配一定的物理内存来存储数据,这部分内存不属于任何文件,内核就使用匿名映射将内存中的 某段物理地址与用户空间一一映射,这样用户就可用直接操作虚拟地址来范围这段物理内存.
至于实际的代码,文件映射的操作就是: open,read,write,close,mmap… 操作的虚拟地址都属于文件映射.
malloc 分配的虚拟地址属于匿名映射.普通文件:
将可执行文件加载到内存中,进行的映射是普通文件的映射。比如data段、 text段等,是私有的文件映射。
匿名文件