内存管理
一 、前言
这篇文章简单介绍操作系统的内存管理机制,包括动态分区分配,分页,分段和段页式。
二、动态分区内存
给了一块很大的内存,如何写一个new和delete做内存分配。虽然这个问题源自于操作系统的内存管理,但现在操作系统基本都用段页式了。而动态分区内存的思路主要用来写程序中的动态申请和回收内存了。
需要一个空闲分区表,记录每个分区是否分配,分区起址,分区长度。
还需要空闲分区链,把多个分区链接起来。
(在实现new和delete时并没有用这样的结构,而是用了类似静态链表的结构)
内存分配和回收
1 起始时内存分区只有一个,是一块很大的内存。进程创建时,从中划分出一块分给进程,剩下的放回空闲分区链中。
2 当进程终止,把内存回收,挂到空闲分区链中,按起始地址排序。
3 可以想想经过多次分配和回收空闲分区链会有很多分区,分配内存需要一定策略。首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法、快速适应算法。
4 由于这种分配,可能产生很多外碎片。也有在回收时合并分区的策略:
回收区与插入点的前一个空闲分区F1相邻接,此时将两个分区合并
回收区与插入点的后一个空闲分区F2相邻接,此时将两个分区合并
回收区与插入点的前,后两个空闲分区相邻接,此时将三个分区合并
回收区既不与F1相邻接,又不与F2相邻接,此时应为回收区单独建立一个新表项
5 也可以引入伙伴系统来优化碎片。按2的幂的大小分配和回收内存,这样分配和回收都可能递归的划分/合并伙伴。会产生一些内碎片。
6可以根据抖动来判断一个内存管理系统的好坏。
保护:通过进程上下界来方式越界。
三、分页
神器的百度百科居然有课本上的内容,搜 基本分页存储管理方式、基本分段存储管理方式、段页式存储管理方式
分配和回收
分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页;相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame)。块的大小一般是512B~8KB。
用一个bit数组(位示图)标识内存的每个块是否已被分配。分配时找到一个未分配的空间分配,bit数组置1;回收时bit数组置0。关于分配和回收还要改一下页表。
地址变换
1 看按箭头的方向看这张图。开始的时候是一个逻辑地址,就是程序中的地址。结果是一个物理地址,就是内存中的地址。比如说程序中的函数在2500号的位置,页大小是1024,则经过编译器编译后得到的逻辑地址是页号为2500/1024=2,页内地址为2500 % 1024=452。而物理地址也由两部分组成,块号(暂时还不知道是多少),块内地址是452。
2 由页号怎么得到块号,内存中用页表来记录这种映射。比如说一个进程有100个页,当这个进程创建,页表中就加100项,每项对应于进程的页到内存块的映射。
3 操作系统只有一个页表,被多进程公用。所以每个进程在页表中的key(页号)是连续存放,另外在访问页表前要知道进程对应的key在页表中的起始位置,还要知道在页表中的长度(比如说前面的100)。起始位置和页表长度放在进程的PCB里,在进程调度后,放到页表寄存器中。根据这两个值就能在页表中找到页的位置了~~。
4 由3知道,页号不用存放在页表中,所以页表就是如图的块号数组。
由于页表用内存实现,所以在访问物理地址前,就要访问多一次内存(读页表)。于是加入了快表来优化,快表是一个硬件实现,用寄存器。用于缓存当前进程最近使用的页-块映射记录。
存储保护:见图中有页号的越界处理。
碎片:每个进程末尾会有一点页内碎片。
虚拟存储:
四、分段
宗旨是进程是分段的,简单来说就是快成若干个模块,有调用过动态链接库就很容易理解这一点。按用户的编程需求,分段更自然。当然这里讲分段和前面的分页都是基础,操作系统都是用段页式的~~
分配和回收:类似于动态分区内存。只不过进程调度时,一次要载入若干个段,而不是整个进程载入。
地址变换:看完分页,这个一看就懂。
保护同分页;
碎片同动态分区内存。
五、段页式
有了分段,分页,段页式就简单了,一图流
六、交换相关策略
交换过程中涉及很多策略
分配多少内存给进程:首先可以确定最小物理块数,之后还有一些其他策略。
什么时候调入页面:
预调入:如果进程的许多页是存放在外存的一个连续区域中,则一次调入若干相邻的页,会比一次调入一个页更高效些。
请求调入:缺页时再调入
调入的页来自哪里:由于与进程有关的文件都放在文件区,故凡是未运行过的页面,都应从文件区调入。而对于曾经运行过但又被换出的页面,由于是被放在对换区,因此在下次调入时,应从对换区调入。由于UNIX系统允许页面共享,因此,某进程所请求的页面有可能已被其它进程调入内存,此时也就无须再从对换区调入。
内存满的时候淘汰哪个页面(页面置换算法):
假定系统为某进程分配了三个物理块,并考虑有以下的页面号引用串:
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
最佳(Optimal)置换算法
先进先出(FIFO)置换算法
最近最久未使用(LRU)置换算法:按上次使用的时间排序,时间最早的一个页被淘汰
Clock置换算法:设置两个位,最近访问位A和,被修改位M。被访问了的页A置为1;淘汰时如果被扫描扫中,如果A=1,把A置为0。否则直接淘汰。
扫描淘汰时,会按AM由00~11的顺序扫描。
最少使用(LFU)置换算法:以最近的使用次时排序。实际上的做法是每次使用把排序值的最高位置1,每隔一段时间把排序值右移。
虚拟内存的原理是局部性原理。
七、总结
看一个内存管理机制其实就是看它的数据结构、分配和回收、地址变换、虚拟存储、存储保护、信息共享、碎片管理。
地址变换:这是指编程时写的地址怎么变换成内存地址。这个概念是由于作业分块才有的。在动态分区分配等方式中,作业是最小的处理单元,编程地址只要是相对作业的起始即可。而在分页,分段中,作业有更小的处理单元,所以地址变换就更复杂。
虚拟存储:如何用小的空间模拟大的空间。有覆盖和交换两种技术。覆盖有点像c语言的空间共用,union。而交换就是把内存中不常用的换到外存。只有分页和分段才能交换,因为它们的粒度更小,可以换。
存储保护:防止程序越界访问其他程序的内存空间。
信息共享:比如说动态链接库,可以在多个进程间共享。
最后列几个相关的概念:
静态重定位是在程序执行之前进行重定位,它根据装配模块将要装入的内存起始位置,直接修改装配模块中的有关使用地址的指令。
动态重定位是指,不是在程序执行之前而是在程序执行过程中进行地址重定位。更确切地说,是在CPU每次访问内存单元前才进行地址变换。