体系结构及内存分配

简介: 体系结构及内存分配

分层结构



  • 内存
  • cpu
  • 外设

1687481239582-40fec1fe-4bce-45af-8bbe-b08860961dd2.png


操作系统最核心的部分就是放在内核中

1687481327354-f9eeedaf-a9e7-4cb2-abe0-33bf427b96e9.png



  • 时钟管理
  • 中断处理
  • 原语 : 处于操作系统最底层, 与硬件直接接触
  • 进程管理、存储器管理等


操作系统内核需要运行在内核态

非内核功能运行在用户态


大内核



大内核的体系结构:


1687481523573-ada7c875-b17d-4784-897c-754b7634ae8e.png


**所有的内核部分都是运行在内核态。 **


优缺点:


  • 优点:

**高性能 **


  • 缺点:

内核庞大, 结构混乱, 难以维持。


微内核



微内核的体系结果


对比大内核, 他只将1687481637252-0dd9a8e2-491a-4688-b08d-7c2ad852315e.png


这些作为内核部分运行在内核态


优缺点:


  • 优点:

内核功能少, 结构清晰, 方便维持。


  • 缺点:

需要频繁的在用户态 和 内核态之间切换 ,性能低。


地址空间 & 地址生成



1687488350492-f75b4464-e605-4e8d-8ea3-0258f84ba678.png


就上图而言, p1, p2 ,p3 ,p4 这四个进程在执行相对应的应用程序, 假设p1 先执行, p4 最后执行,那么我们就可以暂时将p4所需要的资源放到 磁盘中, 暂缓放到内存中 。而将真正需要内存的p1所需要的资源放到 内存中。


内存管理目标


  • 抽象:逻辑地址空间
  • 保护:独立地址空间
  • 共享:访问相同内存
  • 虚拟:更多的地址空间


内存管理方法


  • 程序重定位
  • 分段
  • 分页
  • 虚拟内存
  • 按需分页虚拟内存


实现高度依赖于硬件, 其中**内存管理单元(MMU)**负责处理CPU的内存访问请求


地址空间的定义 & 生成


物理地址空间 : —–直接对应硬件支持的地址空间

逻辑地址空间: ——-一个运行的程序, 他所看到的空间(所拥有的内存范围),是一个一维的线性空间


两者的映射关系是由操作系统去协调


逻辑地址 是如何 对应到 物理地址的 ?


通过MMU表达了这种映射关系


  1. 当cpu要执行某个指令的时候 ,ALU部件(计算机组成原理中的内容)需要这条指令的内容。(也就是逻辑地址的内存内容)
  2. 内存管理单元(MMU)查询逻辑映射表 寻找在逻辑地址和物理地址之间的映射是否存在。
  3. 控制器通过总线向主存发送在物理地址的内存内容的请求


确保访问的内存地址合法

通过下面的步骤进行检查


1687489400174-5d53cf36-54e6-43ef-ae7e-1514c560dcd3.png


连续内存分配



内存的碎片问题


  • 空闲内存不能被利用
  • 外部碎片 ( 在分配单元之间的未使用内存)
  • 内部碎片 ( 在分配单元中的未使用内存 )


分区的动态分配


**简单的内存管理方法: **


  • 当应用程序准许运行时, 分配一个连续的区间
  • 分配一个连续的内存区间给运行的程序以访问数据


分配策略


  • 首次适配(第一匹配分配)
  • 最优适配
  • 最差适配


首次分配算法


按照地址顺序的空间块列表

分配需要寻找一个合适的分区


  • 如果有, 那么就需要检查, 看是否自由分区能够合并于相邻的空闲分区


1687489781445-e580356e-48c0-411e-8e56-a39cfdf88965.png


最优适配算法


** 在内存中找到最小的空闲块, 分配给应用程序**


  • 为了避免分割大的空闲块
  • 为了最小化外部碎片产生的尺寸
  • 需求:


按照尺寸排序的空闲块列表

分配需要寻找一个合适的分区

重新分配需要搜索及合并于相邻的空闲分区


1687490033356-b79b2dd5-ab87-4fc7-8705-ee8e810d2f9c.png


最差匹配算法


为了避免有太多微小的碎片

需求:


  • 按尺寸排列的空闲块列表
  • 分配很快(获得最大的分区)
  • 重新分配需要合并于相邻的空闲分区, 如有, 需要调整空闲块列表


1687490279407-6de0e632-43d0-49ec-81be-70bb7e5439b6.png


三种优缺点比较


image.png


压缩式碎片整理


1.压缩式碎片整理

  • 重置程序以合并碎片
  • 要求所有程序是动态可重置的
  • 问题 :

何时重置 ? (在程序处于等待状态时才可以重置)

需要考虑内存拷贝的开销

1687490988103-982b645e-bddb-4ea6-9c36-0438affbd0b0.png


交换式碎片整理


1.交换式碎片整理

  • 运行程序需要更多的内存时,抢占等待的程序并且回收它们的内存
  • 问题 :


哪些程序应该被回收 ?


  • 情况 :运行中 : P3等待中 : P1 P2 P4内存分布 -> 主存 : OS / P1 / P3 / P2 / P4 磁盘 : 空当P3程序需要更大的内存时 ->内存分布 -> 主存 : OS / P1 / P3 / P2 磁盘 : P4

1687490945511-77644c34-48e9-4962-9349-2d02a71f093b.png


非连续内存分配



为什么要分连续内存分配管理方式 ?


答:连续分配的缺点就是会带来各种缺点, 内存利用率低, 外碎片、内碎片等问题。

随意** **

非连续分配的优点 :


  • 一个程序的物理地址空间时非连续的
  • 更好的内存利用和管理
  • 允许共享代码与数据
  • 支持动态加载和 动态链接


**非连续内存分配机制的缺点 : **


1.如果建立虚拟地址和物理地址之间的转换

  1. 软件方案
  2. 硬件方案


两种硬件方案:


  • 分段机制
  • 分页机制


分段机制



程序的分段地址空间


在程序中会有来自不同文件的函数 ; 在程序执行时, 不同的数据也有不同的字段, 比如 : 堆 / 栈 / .bss / .data 等

分段 : 更好的分离和共享

程序的分段地址空间如下图所示 :

1687492032591-146fd77a-b4cd-4cb0-a0ce-f6c33db91673.png


分段寻址方案


逻辑地址空间连续,但是物理地址空间不连续,使用映射机制进行关联.

一个段 : 一个内存”块”

程序访问内存地址需要 : 一个二维的二元组(s, addr) → (段号, 地址)

操作系统维护一张段表, 存储(段号, 物理地址中的起始地址, 长度限制)

物理地址 : 段表中的起始地址 + 二元组中的偏移地址


1687492172173-3df3d312-ddfe-41f0-912c-93ef4485800c.png

硬件实现方案:


1687492321948-2e1a8d32-de2e-4d59-9503-d7c5d901fe82.png


分页机制



分页地址空间

需要知道页号 + 页类的偏移

划分物理内存至固定大小的帧(Frame)


  • 大小是2的幂, 512 / 4096 / 8192

划分逻辑地址空间至相同大小的页(Page)


  • 大小是2的幂, 512 / 4096 / 8192

建立方案 → 转换逻辑地址为物理地址(pages to frames)


  • 页表
  • MMU / TLB


帧(Frame)

1687492595869-25c5ea8d-07db-40c5-bd0a-9ceae0e4a81b.png

物理内存被分割为大小相等的帧. 一个内存物理地址是一个二元组(f, o) → (帧号, 帧内偏移)

帧号 : F位, 共有2^F个帧

帧内偏移 : S位, 每帧有2^S个字节

物理地址 = 2^S * f + o

(例子 : 16-bit地址空间, 9-bit(512 byte) 大小的页帧 物理地址 = (3,6) 物理地址 = 2^9 * 3 + 6 = 1542)

分页和分段的最大区别 : 这里的 S 是一个固定的数, 而分段中的长度限制不定


页(Page)


1687492787864-c033f047-6608-4f9a-bd03-091be0eb0008.png

一个程序的逻辑地址空间被划分为大小相等的页. 页内偏移的大小 = 帧内偏移的大小 页号大小 <> 帧号大小

一个逻辑地址是一个二元组(p, o) → (页号, 页内偏移)

页号 : P位, 共有2^P个页

页内偏移 : S位, 每页有2^S个字节

虚拟地址 = 2^S * p + o

页的寻址机制


1687492834921-1e09c9e2-4e49-4874-8f04-13bc1e6d0e7d.png

  • 页映射到帧
  • 页是连续的虚拟内存
  • 帧是非连续的物理内存
  • 不是所有的页都有对应的帧


分页机制的偏移大小是固定的。


页表


页表结构


1687604020583-30b429c7-fd96-4c34-9f61-3c881eac17aa.png


1.页表的概述


每一个运行的程序都有一个页表


  • 属于程序运行状态, 会动态变化
  • PTBR : 页表基址寄存器


1.转化后备缓冲区(TLB)


他是一块特殊的缓冲地。也可以说是cache。有效的解决了访问速度的问题。


也就是缓解时间问题


Translation Look-aside Buffer(TLB) 是一个缓冲区. CPU中有快表TLB(可以将经常访问的页表存放在这边)


缓存近期访问的页帧转换表项


  • TLB使用关联内存实现, 具备快速访问性能
  • 如果TLB命中, 物理页号可以很快被获取
  • 如果TLB未命中, 对应的表项被更新到TLB中(x86的CPU由硬件实现, 其他的可能是由操作系统实现)


逻辑框图


1687604745949-1df5d8f6-b23a-46a8-9578-32d8d033a2b0.png


页表的缓冲流程


CPU根据程序的page的页号的若干位, 计算出索引值index, 在页表中搜索这个index, 得到的是帧号, 帧号和原本的offset组成物理地址.


1.二级/多级 页表


上述我们可以知道, 页表可以解决时间上的问题, 但是如何解决空间上的问题呢 ?


这里我们可以通过二级页表乃至多级页表来解决


也就是我们常说的时间换空间


1687605364984-cfd5d336-af21-43c1-b573-8a5765adec01.png


二级页表:


  • 将页号分为两个部分, 页表分为两个, 一级页号对应一级页表, 二级页号对应二级页表.
  • 一级页号查表获得在二级页表的起始地址, 地址加上二级页号的值, 在二级页表中获得帧号
  • 节约了一定的空间, 在一级页表中如果resident bit = 0, 可以使得在二级页表中不存储相关index,而只有一张页表的话, 这一些index都需要保留


1687605547105-51c4a08b-532c-462c-aebd-4dc15e11ea2f.png

  • 通过把页号分为k个部分, 来实现多级间接页表, 建立一棵页表”树”


1.反向页表

简单来说, 我们如果不知道物理地址空间大小, 那么就只能通过逻辑地址空间来建立, 这样就会浪费很多的空间。因为我们不知道实际的物理地址空间。


所以这里假设出了一种想法, 就是通过物理地址空间的大小来建立页表 。这样就可以避免了浪费。


方案一: : 基于页寄存器的方案


1687605936545-424fe235-2020-4a10-b1c8-13f1b95f7cbe.png


在页表中我们要解决的问题就是怎么通过页号 来找到页帧号


存储 (帧号, 页号) 使得表大小与物理内存大小相关, 而与逻辑内存关联减小.


每一个帧和一个寄存器关联, 寄存器内容包括 :


  • resident bit : 此帧是否被占用
  • occupier : 对应的页号 p
  • protection bits : 保护位


实例 :


  • 物理内存大小是 : 4096 * 4096 = 4K * 4KB = 16 MB
  • 页面大小是 : 4096 bytes = 4 KB
  • 页帧数 : 4096 = 4 K
  • 页寄存器使用的空间(假设8 bytes / register) : 8 * 4096 = 32 Kbytes
  • 页寄存器带来的额外开销 : 32K / 16M = 0.2%
  • 虚拟内存大小 : 任意


优势 :


  • 转换表的大小相对于物理内存来说很小
  • 转换表的大小跟逻辑地址空间的大小无关


劣势 :


  • 需要的信息对调了, 即根据帧号可以找到页号
  • 如何转换回来? (如何根据页号找到帧号)
  • 在需要在反向页表中搜索想要的页号


方案二 :基于关联内存的方案


硬件设计复杂, 容量不大, 需要放置在CPU中


  • 如果帧数较少, 页寄存器可以被放置在关联内存中


  • 在关联内存中查找逻辑页号


成功 : 帧号被提取

失败 : 页错误异常 (page fault)


  • 限制因素:


  • 大量的关联内存非常昂贵(难以在单个时钟周期内完成 ; 耗电)

所以这种一般不实用


方案三: 基于哈希(hash)的方案

1687606345756-28941032-0eef-4c5d-9312-33c4776bf7f4.png


哈希函数 : h(PID, p) 从 PID 标号获得页号


在反向页表中通过哈希算法来搜索一个页对应的帧号


  • 对页号做哈希计算, 为了在帧表中获取对应的帧号


  • 页 i 被放置在表 f(i) 位置, 其中 f 是设定的哈希函数


  • 为了查找页 i , 执行下列操作 :


计算哈希函数 f(i) 并且使用它作为页寄存器表的索引, 获取对应的页寄存器

检查寄存器标签是否包含 i, 如果包含, 则代表成功, 否则失败



目录
相关文章
|
6月前
|
虚拟化
操作系统体系结构和内存分层
操作系统体系结构和内存分层
68 0
|
存储 缓存 虚拟化
五、计算机体系结构及内存分层体系
五、计算机体系结构及内存分层体系
五、计算机体系结构及内存分层体系
|
存储 编译器 数据处理
[笔记]Windows核心编程《十三》windows内存体系结构
[笔记]Windows核心编程《十三》windows内存体系结构
168 0
|
算法
【操作系统】第三章:计算机体系结构及内存分层体系(Part2:连续物理内存分配)
【操作系统】第三章:计算机体系结构及内存分层体系(Part2:连续物理内存分配)
234 0
【操作系统】第三章:计算机体系结构及内存分层体系(Part2:连续物理内存分配)
|
自然语言处理 Oracle Java
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构(一)
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构(一)
|
缓存 Oracle Java
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构(二)
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构
<JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构(二)
|
缓存 虚拟化 芯片
【操作系统】第三章:计算机体系结构及内存分层体系(Part1:计算机体系结构)
【操作系统】第三章:计算机体系结构及内存分层体系(Part1:计算机体系结构)
269 0
|
存储 编译器 程序员
[笔记]Windows核心编程《十三》windows内存体系结构
Windows核心编程《十三》windows内存体系结构
216 0
 [笔记]Windows核心编程《十三》windows内存体系结构
|
Java Linux C++
【Java 虚拟机原理】JDK 体系结构 | Java 源码运行原理 | Java 虚拟机内存
【Java 虚拟机原理】JDK 体系结构 | Java 源码运行原理 | Java 虚拟机内存
414 0
【Java 虚拟机原理】JDK 体系结构 | Java 源码运行原理 | Java 虚拟机内存
|
关系型数据库 数据库 PostgreSQL
Postgresql数据库体系结构-进程和内存结构
数据库体系结构-进程和内存结构(Process and Memory Architecture) 进程结构 服务器进程postmaster后台工作进程后端进程 内存结构 本地内存区 work_memmaintenance_work_memtemp_buffers 共享内存区 shared buffer poolWAL buffercommit log 数据库启动过程 数据库连接过程 PostgreSQL是一个client/server架构rdbms,一个服务器上运行多个进程。
2276 0