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