操作系统中的内存管理:分段、分区、分页
操作系统中的内存管理:分段、分区、分页
内存要怎么用起来呢?存储程序的思想,把程序放入内存,程序在CPU中取指执行!
而用户程序有逻辑地址,实际的内存是物理地址,于是先有一个地址重定位的问题。
由于程序载入内存之后,睡眠了的话,还会被移入到磁盘,因此在运行时做重定位更好,这叫做地址翻译。
程序编译好是不用做任何更改的,当要运行的时候,创建进程控制块PCB,这里面就有一个基址,再把PC置为初始地址,基址+逻辑地址=物理地址。
分段
把整个程序放进内存?
不,放入的是程序段、数据段等。
那么,现在的PCB要放每个段的基址,这就形成了一个段表。
此时的寻址就是:段基址+段内偏移。
程序分成多个段,代码段、数据段,每个段在内存中找到空闲的地方,然后把基址记录在LDT中,LDT初始化之后就赋值给PCB,PC指针设置成初值,然后根据PC指针进行取指执行,在每次执行的时候,都查这个LDT表,根据表中的基址和程序中的地址,在这里找到物理地址,然后就可以使用起来内存了。
分区
对程序进行分段,但是怎么找到空闲的内存呢?
对内存进行分区,固定分区与可变分区,当一个段提出请求的时候,就根据首先匹配、最佳匹配、最差匹配等算法进行分配。
操作系统用空闲分区表和已分配分区表来管理内存资源。
但是分区总会造成内存碎片的问题。
分区是虚拟内存上的。
分页
把段请求打散行不行?这就把连续化为离散。
物理内存用分页,每页比较小,最多浪费1页。
用户要分段,物理内存要分页。操作系统既支持段,又支持页。
这个时候的寻址呢?
每个进程得有自己的页表,页号表示逻辑页,而页框号表示物理页。
于是,通过页号能找到物理页,通过页内偏移就找到物理地址了。
利用分区适配算法,在虚拟内存中找出一个空闲分区,放入段,然后将段分页,映射到物理地址。需要用段表记录虚拟内存区域的对应,用页表记录对应页所在物理地址。
快表
单独的分页还不行,因为页小了,页表就变大了。
-
只放用到的页号行吗?但不连续的页号没法随机访问,查起来很慢。
-
使用多级页表呢?就像增加目录一样,但每增加一级,就多了一次访存。
于是,我要是能记住最近访问的页就好了,快表就是用硬件根据页号一步找到页框号。那如果快表里面没有呢?就老老实实去多级页表找。
为什么快表可以?因为程序对地址的访问有局部性!(循环、顺序)
页的换入换出
为什么要换入换出?为了实现虚拟内存!
在用户眼里有4G空闲,实际却不是哦,也就是说用户眼里这样的大内存是换入换出实现的!
换入的核心:请求调页,没有这个页号,就赶紧去磁盘调页,需要中断机制。
换出的算法:FIFO、LRU。
swap 分区就是做这个事:换入、换出 = > 虚拟内存 = > 段页 = > 程序载入 => 进程
什么叫颠簸呢?不断地在磁盘和内存中换入换出,但CPU啥也执行不了。