链接:一个大的程序,可能通过多个.o文件组成,所以通过链接,将多个从零开始描述的.o文件组合到一起,并且使之不发生内存冲突。由此组成成为一个.exe应用程序,但此时该程序还存放在硬盘上。
加载:将上一步中,硬盘上的应用程序,通过一定的偏移量加载到内存中。此时的地址依然是逻辑地址。
具体流程如下图:
外部碎片:在分配单元间未使用的内存
内部碎片:在分配单元中未使用的内存
3.4.2 分区的动态分配 什么时候分配?应用程序启动,运行栈加载到内存的时候,分配一块连续的内存空间
应用程序加载数据时
内存分配算法 1. 首次适配如要分配N byte,在内存中查找第一个可用(>=N)的空闲块,以满足最快分配。
需求:1. 按照地址排序; 2. 分配需要寻找合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:实现简单; 易于产生更大数据块。
劣势:会产生外部碎片; 不确定性。
如要分配N byte,在内存中查找第一个可用(>=N)的且最小的空闲块,以满足最快分配。更大的利用小空间。
需求:1. 按照剩余空间大小排序; 2. 分配需要寻找 最 合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:实现简单; 适合大量分配小内存。
劣势:重分配慢; 易产生大量微小的外部碎片。
如要分配N byte,在内存中查找第一个可用(>=N)的且最大的空闲块,以满足最快分配。避免出现大量微小空间。
需求:1. 按照剩余空间大小排序(倒序排列); 2. 分配需要寻找 最 合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:适合大量分配中等大小内存。
劣势:重分配慢; 易产生外部碎片; 会破坏大的空闲块,使更大的应用无法分配。
将非运行时应用占用的内存移动到相邻的一处内存,以减少应用间的外部碎片
3.4.4 交换式碎片整理利用虚拟内存,将非运行时应用占用的内存移动到虚拟内存,以使的运行时应用有更大的空闲空间使用。
3.5 非连续内存分配优点:
内存分配在物理地址空间是非连续的
可以更好,最大化的利用物理内存和管理
允许共享代码和数据(贡献库等、、)
支持动态加载和动态链接
缺点:
内存管理本身的一些维护开销
硬件的配合和支持(分段和分页)
3.5.1 分段(Segmentation)为了更好的分离和管理。
使用分断管理机制后,在逻辑地址层面,地址看上去是连续的,而在物理地址层面,可以将不同的代码段分离出来管理,从而实现共享,管理,权限保护等。
分断寻址方案 3.5.2 分页(Paging)先划分物理内存至固定大小的帧(Frame),用二元组(f,o)表示帧号和帧内偏移;划分逻辑地址空间至相同大小的页(Page),用二元组(p,o)表示页号和页内偏移。帧更像是相框,里面啥也没有,放了照片(逻辑页面)才有意义。
物理寻址方式例题:16-bit的地址空间,512byte大小的页帧大小,则物理地址为(3,6)的实际地址是多少?
解:
每个运行程序都有一个页表,属于程序的运行状态,会动态的发生改变。
缺点:通过分页实现的内存映射,需要进行两次查询(页表查询,物理地址访问)
页表会占用额外的内存,假如64bit机器的每页大小为1024byte,则最大会有2^54个页号
每个应用都有一份页表,对于问题2,就更加麻烦了
上述问题,可以使用缓存和间接访问两种方式解决。
3.5.4 页表的优化 TLB(Translation Look-aside Buffer)