自学自用 = B站(操作系统_清华大学(向勇、陈渝)) 未完待续。。 (2)

链接:一个大的程序,可能通过多个.o文件组成,所以通过链接,将多个从零开始描述的.o文件组合到一起,并且使之不发生内存冲突。由此组成成为一个.exe应用程序,但此时该程序还存放在硬盘上。

加载:将上一步中,硬盘上的应用程序,通过一定的偏移量加载到内存中。此时的地址依然是逻辑地址。

具体流程如下图:

image

3.3.2 物理地址生成过程 graph LR A[CPU加载逻辑地址内容] --> B{查看MMU中是否映射了物理地址} B --> |有| L[获得物理地址] B --> |没有| C{到主存中查找是否有物理地址映射表} C --> |有| L L--> D[读取物理地址的内容] 3.4 连续内存分配 3.4.1 内存碎片

外部碎片:在分配单元间未使用的内存

内部碎片:在分配单元中未使用的内存

3.4.2 分区的动态分配 什么时候分配?

应用程序启动,运行栈加载到内存的时候,分配一块连续的内存空间

应用程序加载数据时

内存分配算法 1. 首次适配

如要分配N byte,在内存中查找第一个可用(>=N)的空闲块,以满足最快分配。

需求:1. 按照地址排序; 2. 分配需要寻找合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:实现简单; 易于产生更大数据块。
劣势:会产生外部碎片; 不确定性。

2. 最优适配

如要分配N byte,在内存中查找第一个可用(>=N)的且最小的空闲块,以满足最快分配。更大的利用小空间。

需求:1. 按照剩余空间大小排序; 2. 分配需要寻找 最 合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:实现简单; 适合大量分配小内存。
劣势:重分配慢; 易产生大量微小的外部碎片。

3. 最差适配

如要分配N byte,在内存中查找第一个可用(>=N)的且最大的空闲块,以满足最快分配。避免出现大量微小空间。

需求:1. 按照剩余空间大小排序(倒序排列); 2. 分配需要寻找 最 合适的空闲块; 3. 内存回收后,要将相邻块进行合并。
优势:适合大量分配中等大小内存。
劣势:重分配慢; 易产生外部碎片; 会破坏大的空闲块,使更大的应用无法分配。

3.4.3 压缩式碎片整理

将非运行时应用占用的内存移动到相邻的一处内存,以减少应用间的外部碎片

3.4.4 交换式碎片整理

利用虚拟内存,将非运行时应用占用的内存移动到虚拟内存,以使的运行时应用有更大的空闲空间使用。

3.5 非连续内存分配

优点:

内存分配在物理地址空间是非连续的

可以更好,最大化的利用物理内存和管理

允许共享代码和数据(贡献库等、、)

支持动态加载和动态链接

缺点:

内存管理本身的一些维护开销

硬件的配合和支持(分段和分页)

3.5.1 分段(Segmentation)

为了更好的分离和管理。

使用分断管理机制后,在逻辑地址层面,地址看上去是连续的,而在物理地址层面,可以将不同的代码段分离出来管理,从而实现共享,管理,权限保护等。

image

分断寻址方案

image

3.5.2 分页(Paging)

先划分物理内存至固定大小的帧(Frame),用二元组(f,o)表示帧号和帧内偏移;划分逻辑地址空间至相同大小的页(Page),用二元组(p,o)表示页号和页内偏移。帧更像是相框,里面啥也没有,放了照片(逻辑页面)才有意义。

物理寻址方式例题:

16-bit的地址空间,512byte大小的页帧大小,则物理地址为(3,6)的实际地址是多少?
解:

512 = 2^9 // 页帧需要使用9bit表示 16-9 = 7 // 页号需要使用7bit表示 所以实际物理地址的二进制表示为 0000011 000000110 转为十进制为1542,也可以用 3 * 512 + 6 = 1542

image

3.5.3 页表的缺点

每个运行程序都有一个页表,属于程序的运行状态,会动态的发生改变。

缺点:

通过分页实现的内存映射,需要进行两次查询(页表查询,物理地址访问)

页表会占用额外的内存,假如64bit机器的每页大小为1024byte,则最大会有2^54个页号

每个应用都有一份页表,对于问题2,就更加麻烦了

上述问题,可以使用缓存和间接访问两种方式解决。

3.5.4 页表的优化 TLB(Translation Look-aside Buffer)

image

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywswg.html