早期计算机编程并不需要过多的存储管理,随着计算机和程序越来越复杂,存储管理成为必要。
存储管理主要解决三个问题:
有以下三种分配方法
单一连续分配是最简单的内存分配方式,只能在单用户、单进程的操作系统中使用。
该方法将内存分为系统区和用户区,系统区内存只能给操作系统使用,用户区的内存只能给用户使用。
固定分区分配是支持多道程序的最简单存储分配方式,内存空间被划分为若干固定大小的区域(分区),每个分区只提供给一个程序使用,互不干扰。
根据进程实际需要,动态分配内存空间。
下面介绍该方法相关的数据结构、分配算法:
内存回收区在内存中有四种情况(假设使用空闲链表保存空闲区):
字块是相对物理设备的定义,页面则是相对逻辑空间(进程空间)的定义。
页式存储管理就是将进程逻辑空间等分成若干大小的页面,相应的把物理内存空间分成与页面大小相同的物理块,以页面为单位把进程空间装进物理内存中分散的物理块(字块)。
页面大小 应该适中,过大难以分配,过小内存碎片过多,页面大小通常是512B~8K。
如何知道进程的页面分配到哪一个物理块(字块)呢?
页表:记录进程逻辑空间与物理空间的映射。有两项:页表、字块。
页地址对应字的地址,页地址也是分为两部分,前m位(页号)是页面在页表的索引,得到该页的物理块(字块);后b位(页内偏移)指定页面在物理块(字块)中的地址。
页表在现代计算机系统中的问题:
现代计算机系统中,可以支持非常大的逻辑地址空间(232~264) ,这样,页表就变得非常大,要占用非常大的内存空间。比如,具有32位逻辑地址空间的分页系统,规定页面大小为4KB,则在每个进程页表中的页表项可达1M(220)个,如果每个页表项占用1Byte,故每个进程仅仅页表就要占用1MB的内存空间。
为解决这一问题,引出多级页表。只需要在运行时候加载根页表,之后按需查找二级页表……
页式存储管理的缺点:有一段连续的逻辑分布在多个页面中,将大大降低执行效率。
将进程逻辑空间划分(非等分)成若干段,段的长度由连续逻辑的长度决定。比如,逻辑里面有主函数MAIN、子程序段X、子函数Y等,按照每一个函数的逻辑长度分配逻辑空间(段)。
段表:记录进程逻辑空间与物理空间的映射。有三项:段号、基址、段长。
段地址:段号、段内偏移两部分组成。类比页地址。
分页可以有效提高内存利用率(虽然说存在页内碎片),分段可以更好满足用户需求。二者取其优,结合为段页式存储管理。
段页式存储管理先将逻辑空间按段式管理分成若干段,再把段内空间按页式管理等分成若干页。
段页地址:由三部分组成。段号是进程逻辑空间具体哪一段;段内页号是段里具体某一页;页内地址是某一页里具体的字。
一个游戏十几G,物理内存只有4G,那这个游戏是怎么运行起来的?
为什么需要虚拟内存?
虚拟内存是操作系统内存管理的关键技术,使得多道程序运行和大程序运行成为现实。
工作方式:把程序使用内存划分,将部分暂时不使用的内存放置在辅存中,使用辅存保存之后可能用到的部分。
局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访的存储单元都趋于聚集在一个较小的连续区域中。
程序运行时,无需全部装入内存,装载部分即可;如果访问页不在内存,则发出缺页中断,发起页面置换;从用户层面看,程序拥有很大的空间,即是虚拟内存。
虚拟内存实际是对物理内存的补充,速度接近于内存,成本接近于辅存。
高速缓存替换 | 页面替换 | |
---|---|---|
时机不同 | CPU读取缓存时没有找到对应数据, 缓存需要从主存中载入相关数据 | 主存缺页时,主存需要从辅存载入页面数据 |
层次不同 | Cache-主存层次 | 主存-辅存层次 |
目的不同 | 解决速度问题 | 解决容量问题 |
这也是为什么计算机存储器分层的一个原因。