连续分配:只能将一个进程放入一个连续的足够存放进程大小的内存空间
考虑支持多道程序的两种连续分配方式:
1.固定分区分配:缺乏灵活性,会产生大量的内部碎片,内存的利用率很低。
2.动态分区分配:会产生很多外部碎片,虽然可以用“紧凑”技术来处理,但是“紧凑”的时间代价很高
如果允许将一个进程分散地装入到许多不相邻的分区中,便可充分地利用内存,而无需再进行“紧凑”
基于这一思想,就有了非连续分配方式,或者叫离散分配方式
连续分配:为用户进程分配的必须是一个连续的内存空间
非连续分配:为用户进程分配的可以是一些分散的内存空间
固定分区分配——》非连续分配
基本分页存储管理的思想:把内存分为一个个相等的小分区,再按照分区大小把进程拆分成一个个小部分
将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个“页框”,或称“页帧”、“内存块”、“物理块”。每个页框有一个编号,即“页框号”(或者“内存块号”、“页帧号”、“物理块号”)页框号从0开始。
将用户进程的地址空间也分为与页框大小相等的一个个区域,称为“页”或“页面”。每个页面也有一个编号,即“页号”,页号也是从0开始。
(注:进程的最后一个页面可能没有一个页框那么大。因此,页框不能太大,否则可能产生过大的内部碎片)
操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说:进程的页面与内存的页框有一一对应的关系。
各个页面不必连续存放,也不必按先后顺序来,可以放到不相邻的各个页框中。
将进程地址空间分页之后,操作系统该如何实现逻辑地址到物理地址的转换?
思想:
模块在内存中的的“起始地址”+目标内存单元相对于起始位置的“偏移量”
将进程的逻辑地址空间分页,假设每页大小为50B
CPU执行指令1,需要访问逻辑地址为80的内存单元,如何转换为物理地址?
1.要算出逻辑地址对应的页号
2.要知道该页号对应页面在内存中的起始地址
3.要算出逻辑地址在页面内的“偏移量”
4.物理地址=页面始址+页内偏移量
计算页号和偏移量:
页号=逻辑地址/页面长度(取除法的整数部分)
页内偏移量=逻辑地址%页面长度(取除法的余数部分)
页面在内存中的起始位置:操作系统需要用某种数据结构记录进程各个页面的起始位置。
为了方便计算,页面大小一般设为2的整数幂
假设用32个二进制位表示逻辑地址,页面大小为2^12 B = 4096 B = 4 KB
0号页的逻辑地址空间应该是0~4095,用二进制表示应该是: 00000000000000000000000000000000~ 00000000000000000000111111111111
1号页的逻辑地址空间应该是4096~8191,用二进制表示应该是: 00000000000000000001000000000000 ~ 00000000000000000001111111111111
2号页的逻辑地址空间应该是8192~12287,用二进制表示应该是: 与另一种算法的结果对比: 00000000000000000010000000000000 ~ 00000000000000000010111111111111
Eg:逻辑地址2,用二进制表示应该是00000000000000000000000000000010 若0号页在内存中的起始地址为x,则逻辑地址⒉对应的物理地址应该是X+000000000010
Eg:逻辑地址4097,用二进制表示应该是00000000000000000001000000000001 若1号页在内存中的起始地址为X,则逻辑地址4097对应的物理地址应该是X+000000000001
结论:
如果每个页面大小为2^k B,用二进制数表示逻辑地址,则末尾K位就是页内偏移量,其余部分就是页号
eg.
00000000000000000001000000000002
1就是页号,2就是页内偏移量
对于32位二进制来表示逻辑地址:
0~11位就是页内偏移量,12~31位就是页号
如果有K位表示“页内偏移量”,则说明该系统中一个页面的大小是2^K 个内存单元
如果有M位表示“页号”,则说明在该系统中,一个进程最多允许有2^M 个页面
为了能知道进程的每个页面在内存中存放的位置,操作系统要为每个进程建立一张页表。
1.一个进程对应一张页表
2.进程的每一页对应一个页表项
3.每个页表项由“页号”和“块号”组成
4.页表记录进程页面和实际存放的内存块之间的对应关系
5.每个页表项的长度是相同的,页号是“隐含”的
为什么每个页表项的长度是相同的,页号是“隐含”的?
Eg:假设某系统物理内存大小为4GB,页面大小为 4KB,则每个页表项至少应该为多少字节?
4GB = 2^32 B,4KB = 2^12 B
因此4GB的内存总共会被分为2^32 / 2^12 =2^20个内存块,因此内存块号的范围应该是0~2^20-1
因此至少要20个二进制位才能表示这么多的内存块号,因此至少要 3个字节才够 (每个字节8个二进制位,3个字节共24个二进制位)
各页表项会按顺序连续地存放在内存中
如果该页表在内存中存放的起始地址为x,则 M号页对应的页表项一定是存放在内存地址为:X+3*M
因此,页表中的“页号”可以是“隐含”的。
只需要知道页表存放的起始地址和页表项长度,即可找到各个页号对应的页表项存放的位置
在本例中,一个页表项占3B,如果进程由n个页面,则该进程的页表总共会占3*n个字节
