当前位置: 首页 > news >正文

3.7 分段 Segmentation

进程的地址空间是结构化的,对应的,我们将其划分为不同的段:代码段、数据段、堆段、栈段等,每个段之间相互独立互不影响。堆段和栈段的增长不会导致其他段被覆盖。每个段都有自己的地址,都可以从 0 开始。

相比分页,分段更适合做共享库。在分段下,可以直接映射一整个代码段,而在分页下,需要组合页面来完成“代码段”的映射。

3.7.1 Implementation of Pure Segmentation 纯粹分段的实现

只对内存进行分段,不做分页。

分页是按照固定的大小分割内存,分段则是按照结构来划分,每个段的大小都不一致。那么在只有分段没有分页的内存中,换出与换入段的大小不一致,容易导致大量内存碎片的产生,称为外部碎片(external fragmentation)或者棋盘形碎片(checkerboard)

这些内存碎片可以通过内存紧缩来回收,通过调整每个段的位置,消除段之间的空洞,当然这会消耗性能。

3.7.2 Segmentation with Paging: MULTICS 分段与分页的结合:MULTICS

结合了分段和分页的虚拟内存组织形式称为段页式,段页式结合了分段和分页的优点

  • 分页:统一的页面大小,只用加载需要的页面
  • 分段:易于编程、模块化、保护、共享

multics 每个段的虚拟地址空间是 36 位,并且每个段作为一个独立的虚拟地址空间进行分页,每个段都有一个段表,结构如下:

字段 长度(bit) 作用
页表描述符 18 指向该段的地址
段长度 9 说明段的长度,以页为单位
页面大小 1 0:1024字,1:64字
是否分页 1 0:分页,1:不分页
- 1 -
其他 3 -
保护位 3 -

1

虚拟地址分为段号、页号和页内偏移。寻址时:

  1. 根据段号找到对应的段描述符号
  2. 检查段的页面是否在内存中,如果不在就产生一个段错误,如果在就找到这个段。如果违反了段的访问保护限制,就发出一个越界错误
  3. 根据页号寻找页面,如果页面不在内存中则产生一个缺页中断
  4. 根据业内偏移量找到需要访问的地址

3.7.3 Segmentation with Paging: The Intel x86 分段与分页的结合:The Intel x86

相比 MULTICS,x86 的段更少但是容量更大。几乎没有进程会超过 1000 个段,但是有很多程序需要大段。

  • MULITCS: 256K 个独立的段,每个段最长可以容纳 64K 个 36 位字
  • x86: 16K 个独立的段,每个段最多可以容纳 10 亿个 32 位字

从 x86_64 开始,不再支持分段模式,但是依然保留了分段模式的机制。

在 x86 中,虚拟内存的核心是 局部描述符表LDT(Local Descriptor Table)全局描述符表GDT(Global Descriptor Table)。每个程序都有自己的 LDT,所有程序共享一个 GDT。

  • LDT: 描述每个程序的段,包括代码段、数据段、堆栈等。
  • GDT: 描述系统段,包括操作系统本身。

为了访问一个段,x86 需要将段的 selector 装入段寄存器中,不同的段对应不同的段寄存器,代码段对应 CS,数据段对应 DS。

  1. 先根据标志位选择 LDT 或者 GDT
  2. 选择将 selector 加载到内部的寄存器中,将低三位清零
  3. 将 LDT 或者 GDT 的地址加到寄存中,就得到了对应描述符的地址。

2

字段 长度(bit) 作用
index 13 对应段描述符的地址
- 1 0表述GDT 1表示LDT
- 2 保护位

段描述符大小 8 字节,结构如下:
3

字段 长度 作用
Base 32 段的基地址
Limit 20 段的长度
G 1 0:Limit 以字节为单位,1:Limit 以页为单位

注意:为 0 的段描述符是禁用的,用于表示段寄存器不可用。如果从寄存器中拿到了一个为 0 的段描述符,就触发一次 trap。

拿到段描述符后:

  1. 根据 Limit 检查偏移量是否在段内。如果不在段内,触发一次 trap

    如果 G 为 0,那么 Limit 以字节作为单位,最大为 1MB。当 G 为 1 时,Limit 以页面作为单位。

  2. 基地址 + 偏移量 = 线性地址

    如果禁止分页,那么线性地址就作为物理地址,从而可以得到一个纯分段的虚拟内存。

    如果允许分页,那么线性地址就作为虚拟地址,通过页表映射到物理地址。

在 32 位虚拟内存和 4 KB 页下,一个段可能包含百万数量的页面,因此使用两级映射减少页表的大小。

每个进程都有一个由 1024 个 32 位表项组成的页目录(page directory),通过一个全局寄存器定位。每个目录的项都指向一个包含 1024 个 32 位表项的页表,页表项指向页帧。

4

对应的,线性地址被划分为三部分:页目录、页面、页偏移量。

  • 页目录:作为索引,在页目录表中定位页表
  • 页面:作为索引,在页表中定位页面的位置
  • 页偏移量:用于寻找需要访问的物理地址

一个页表包含 1024 个页面,可以管理 4MB 内存,对于小于 4MB 的段,页目录中只有一个表项指向一个唯一的页表。这种方式较短的段的开销只有两个页面。

为了避免重复的内存访问,x86 使用 TLB 缓存近期使用过的页面映射。

某些应用程序不需要分段,需要一个独立的分页的 32 位地址空间。可以将所有的段寄存器设置为同一个 selector,将段描述符的基地址设置为 0, Limit 设置到允许的最大。

事实上,目前所有的 x86 系统都是这样的,只使用一个段,本质上是存粹的分页虚拟内存系统。

http://www.jsqmd.com/news/120677/

相关文章:

  • Excalidraw常见问题汇总:官方FAQ精华整理
  • 从人到人机再到人机环境:东西方思想的融合
  • 近两百万人围观的Karpathy年终大语言模型清单,主角是它们
  • Excalidraw鱼骨图绘制:根本原因分析法实践
  • Excalidraw暗黑模式设置:夜间使用的护眼方案
  • Excalidraw与AI结合前景:未来功能演进预测
  • 分层模糊系统:梯度下降与递推最小二乘法联合辨识研究(Matlab代码实现)
  • Excalidraw用户体验监控:前端性能指标采集
  • Excalidraw类图绘制:面向对象设计辅助
  • 远程连接内网服务器
  • Excalidraw构建流程分析:Webpack/Vite打包配置
  • 基于Spring Boot技术的数字乡村农作物智慧管理系统设计毕设
  • 【自动驾驶基础】LDM(Latent Diffusion Model) 要点总结
  • Linux中级の配置四层负载均衡(Nginx做的假四层)
  • ExcalidrawOKR目标看板:团队目标对齐工具
  • Excalidraw网格与参考线设置:提升对齐精度
  • 【电力系统】采用有源电力滤波器抑制谐波研究(Simulink仿真实现)
  • PyTorch中通过设置随机种子使训练结果可复现
  • 基于Spring Boot的医院预约挂号系统的设计与实现毕业设计源码
  • A server error occurred. Please contact the administrator的问题解决
  • Excalidraw会议纪要模板:图文结合更清晰
  • 基于Spring Boot的在线考试系统设计与实现毕业设计
  • 2025年度绵阳高中复读学校口碑推荐榜单,名办高中/学校/实验中学/高中复读学校/中学/实验学校/高中高中复读学校企业怎么选择 - 品牌推荐师
  • 利用 SSI-COV 算法自动识别线状结构在环境振动下的模态参数研究(Matlab代码实现)
  • Excalidraw能否保存为PDF?打印输出最佳实践
  • 在 OpenEuler 系统中遇到 checking for icu-uc icu-i18n... no 和 configure: error: ICU library not found 这类错误解
  • MySQL主从同步架构配置笔记
  • 基于Spring Boot的新生报到管理系统的设计与实现毕业设计源码
  • 精品UI知识付费系统源码 响应式视频教程知识付费软件下载网站模板
  • 143_尚硅谷_数组的快速入门