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

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

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

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

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

分段

把整个程序放进内存?

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

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

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

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

分区

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

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

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

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

分区是虚拟内存上的。

分页

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

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

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

这个时候的寻址呢?

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

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

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

快表

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

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

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

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

页的换入换出

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

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

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

换出的算法:FIFO、LRU。

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

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

comments powered by Disqus
相关文章
我的博客构建方法及历史

简介 回想自己的博客系统,是从什么时候开始建立的呢? 我翻阅了域名购买记录、服务器购买记录、GitHub 仓库等。 最早在 2019年3月 购买了 dfface.com 的域名,但我怀疑最早的网站不在那个时候,应该还要更早,更早的那一波可能采用了 GitHub Pages。

阅读更多
如何在 React 中轻松路由?使用 React Router!

开始 tsx 复制 已复制! import React from "react"; import ReactDOM from "react-dom/client"; import { createBrowserRouter, RouterProvider, } from "react-router-dom"; import Root from "./routes/root"; const router = createBrowserRouter([ { path: "/", element: <Root />, }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> ); root 路由比较特殊。

阅读更多
动态连通性问题中的并查集

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

阅读更多