🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 程序对内存的管理 ![](https://img.kancloud.cn/49/63/49636b463e0b73fcd13b2615eb67e728_111x400.png) - 程序(进程)将内存分成一个个分隔的片段,我们叫做段( segment) - 段和段之间应该有一定的空闲内存,这样方便各个段继续分配内存 - 进程表中需要存放到各个段的指针,方便进程获取各个段的数据 段和段内存随着增长会不会碰撞?如何解决这个问题 答案:虚拟化 Why:资源稀缺的时候,就应该想到虚拟化,让资源可以被无限抽象例如货币) ### 段的一种虚拟化 ![](https://img.kancloud.cn/57/54/575433b0afb9e79430dc301fb4216892_400x321.png) - Stack 段被抽象成几个字段 - 每个段有一个段描述符然后指向 page table中的条目 ## 堆和栈 ![](https://img.kancloud.cn/36/fc/36fce87c2d7c8f392f76196f7aca910a_400x270.png) - 栈中的数据总是差不多大小 - 堆用来存放不规则的数据 堆作为一个段也是虚拟化的 ![](https://img.kancloud.cn/c7/53/c753f319ee3ec24f04fa764123acb56e_400x308.png) ## 堆中如何管理内存 - 将堆中的内存组织成一个每个node一样大的双向链表 - 每次分配从Free指针开始分配 ![](https://img.kancloud.cn/be/85/be85d707afd075dcdd93ff31cf1b71bb_400x106.png) 实际效果 ![](https://img.kancloud.cn/f7/a9/f7a941325a2f78331d9abf333a04247c_157x250.png) - 一个Bock node挨着一个 block - 每个bock取出两个字(一个字32位4字节), 一个代表链表的next,一个代表链表的prev ## 堆的分配与回收 ### 方式一:相同大小的Block 分配1 ![](https://img.kancloud.cn/6c/b8/6cb88f6b00a8840c92289ed29410f93f_400x110.png) 分配2 ![](https://img.kancloud.cn/1d/20/1d20b821e6dd5963837c35446ce1a475_400x107.png) 分配3 ![](https://img.kancloud.cn/f9/6c/f96c882046e33b345141117cca6ac905_400x106.png) 回收1:对回收Block 进行标记 ![](https://img.kancloud.cn/16/3f/163f3ac496f12143b0857f4e672fce71_400x110.png) 回收2 ![](https://img.kancloud.cn/1d/0d/1d0ddbb310201be1ebfd7fcd309a4f6e_400x107.png) 回收3:把回收内存清空,并合并使用的Block ![](https://img.kancloud.cn/d3/10/d3108dbe58559ee7e7269aa6543821ff_400x137.png) ### 方式二:不同大小的块 ![](https://img.kancloud.cn/f0/95/f0953963f049970d439344ad355c0642_400x356.png) 缺点: 1. 这个基于链表的抽象,需要提前分配很多内存 2. 如果产生跨页,则可能会有缺页中断 有没有性能更高、占用内存更少的做法? ### 方式三:类Unix 主流做法(Slot) - 当你需要1.5kb的对象,会在缓存表中记录条目,并指向页中提取准备好的槽 - 相同的缓存大多在一个页表中 ![](https://img.kancloud.cn/3e/a4/3ea4878516f5e0813efdc73916100e96_400x333.png) 程序语言也用so法管理内存吗? - 部分没有虚拟机的语言,刨建对象是创建在 cache-slot上的。比如c的malloc就是直接分配一个合适大小的 cache - 还有一些有虚拟机的语言,有自己的内存管理 - 另一方面,程序语言不需要像操作系统一样预留大量类型的slot等待分配(因为程序大小不一,功能不一样