内存管理:分段、分区、分页

内存要怎么用起来呢?存储程序的思想,把程序放入内存,程序在CPU中取指执行!

而用户程序有逻辑地址,实际的内存是物理地址,于是先有一个地址重定位的问题。

由于程序载入内存之后,睡眠了的话,还会被移入到磁盘,因此在运行时做重定位更好,这叫做地址翻译

程序编译好是不用做任何更改的,当要运行的时候,创建进程控制块PCB,这里面就有一个基址,再把PC置为初始地址,基址+逻辑地址=物理地址。

分段

把整个程序放进内存?

不,放入的是程序段、数据段等。

那么,现在的PCB要放每个段的基址,这就形成了一个段表

此时的寻址就是:段基址+段内偏移。

程序分成多个段,代码段、数据段,每个段在内存中找到空闲的地方,然后把基址记录在LDT中,LDT初始化之后就赋值给PCB,PC指针设置成初值,然后根据PC指针进行取指执行,在每次执行的时候,都查这个LDT表,根据表中的基址和程序中的地址,在这里找到物理地址,然后就可以使用起来内存了。

分区

对程序进行分段,但是怎么找到空闲的内存呢?

对内存进行分区,固定分区与可变分区,当一个段提出请求的时候,就根据首先匹配、最佳匹配、最差匹配等算法进行分配。

操作系统用空闲分区表和已分配分区表来管理内存资源。

但是分区总会造成内存碎片的问题。

分区是虚拟内存上的。

分页

把段请求打散行不行?这就把连续化为离散。

物理内存分页,每页比较小,最多浪费1页。

用户要分段,物理内存要分页。操作系统既支持段,又支持页。

这个时候的寻址呢?

每个进程得有自己的页表页号表示逻辑页,而页框号表示物理页。

于是,通过页号能找到物理页,通过页内偏移就找到物理地址了。

利用分区适配算法,在虚拟内存中找出一个空闲分区,放入段,然后将段分页,映射到物理地址。需要用段表记录虚拟内存区域的对应,用页表记录对应页所在物理地址。

快表

单独的分页还不行,因为页小了,页表就变大了。

  • 只放用到的页号行吗?但不连续的页号没法随机访问,查起来很慢。
  • 使用多级页表呢?就像增加目录一样,但每增加一级,就多了一次访存。

于是,我要是能记住最近访问的页就好了,快表就是用硬件根据页号一步找到页框号。那如果快表里面没有呢?就老老实实去多级页表找。

为什么快表可以?因为程序对地址的访问有局部性!(循环、顺序)

页的换入换出

为什么要换入换出?为了实现虚拟内存!

在用户眼里有4G空闲,实际却不是哦,也就是说用户眼里这样的大内存是换入换出实现的!

换入的核心:请求调页,没有这个页号,就赶紧去磁盘调页,需要中断机制。

换出的算法:FIFO、LRU。

swap 分区就是做这个事:换入、换出 = > 虚拟内存 = > 段页 = > 程序载入 => 进程

什么叫颠簸呢?不断地在磁盘和内存中换入换出,但CPU啥也执行不了。

相关文章
动态连通性问题中的并查集

简介 union-find 是为了解决动态连通性问题而提出来的一个算法,而对应的数据结构被称为并查集,集即集合。 动态连通性问题,可以联想到编程中两个变量名是否等价、集合中两个元素是否属于同一个集合、图中两个节点是否连通等。 简单地说,给你一些相连的节点对,让你判断一个新的节点对是否相连。

阅读更多
Remarkable2 配置中文字体与其他 Tips

动机 每次更新系统之后,我的字体就没了,我哭😭 主旨 导入文档 下面尝试导入 PDF、EPUB 来看看阅读效果。首先肯定要去官方的支持网站,看看用户手册。 官方的导入方案中,总的来说就两种,一个是通过它的云同步服务,在客户端程序上导入,另一个就是通过 USB 连接到电脑,通过浏览器网页导入。

阅读更多
BlockSuite 一款 Block Style 的编辑器,仅仅是编辑器!

先说结论 我的博客不太适合用 BlockSuite 作为编辑器,因为: 不知道如何渲染,我可以编辑,但是如何展示给匿名用户看? SEO 不太明确,也想着转成 HTML 来做,但是成本太高? 其他博主的调研:https://blog.nineya.com/archives/154.html 开始! 学习一下:https://block-suite.com/ Scratch(QuickStart) 简单安装一下,目前是 canary 版本, AFFiNE 也是用的这个版本,每次都打包的 master 分支,基本上每天都有更新。

阅读更多