段式虚拟存储器

页式按固定大小切,段式按程序的逻辑结构切:主程序段、子程序段、数据段、栈段各是一段,长度由内容决定,因而可变。

这一条”长度可变”是段式与页式一切差别的源头:地址不能靠拼接得到(必须做加法)、必须存段长(必须做越界检查)、会产生外部碎片、但也因此便于共享和保护。

机制

地址结构是二维的

段号选哪一段段内偏移到段长

段内偏移的取值范围由该段的实际长度决定,不是由位数决定——这就是”地址是二维的”的含义:段号和段内偏移是两个独立的量,不能像页式那样合成一个连续的一维地址。

程序员在段式系统中能看见段号(例如汇编中的段寄存器),而页式的分页对程序员完全不可见。这一条是两者在”透明性”上的实质差别。

段表与地址转换

段表每项对应一个段:

字段作用
段长越界检查的依据——页式没有这一项
段基址(起始物理地址)转换的基准
有效位该段是否在主存
权限位读/写/执行

转换过程:物理地址段基址段内偏移加法,不是拼接并且必须先做越界检查:段内偏移段长越界异常页式不需要越界检查,因为页内偏移的位数恰好等于页大小的对数,它天然不可能超出页的范围。“段式要查段长、页式不用”是两者最常考的一处差别。

优点与代价

优点全部来自”段是一个逻辑单位”:

  • 便于共享:一个子程序段可以被多个进程的段表同时指向,共享的粒度是”一个完整的模块”,语义清晰
  • 便于保护:权限按段设置,代码段设为只读且可执行、数据段设为可读写不可执行,正好对应逻辑含义
  • 便于动态增长:栈段和堆段可以在运行中变长
  • 便于模块化编译与链接

代价全部来自”长度可变”:

  • 产生外部碎片(页式只有内部碎片)
  • 分配算法复杂(首次适应、最佳适应等,见 OS 3.1.2)
  • 换入换出的单位大小不定,I/O 效率不如定长的页

边界

段式的物理地址靠加法得到,页式靠拼接。 这一条决定了段式的段基址可以是任意地址,而页式的页框起始地址一定是页大小的整数倍。

段的共享是”共享一个段表项指向的段”,页的共享是”多个页表项指向同一页框”。 两者都能共享,但段的共享单位有逻辑含义,页的共享单位没有。

段号的位数决定最多能有多少段,段内偏移的位数决定单段最大长度——但实际段长由段表中的段长字段决定,通常小于位数所允许的上限。

分段是程序员可见的,分页对程序员透明。 这一条在 OS 3.1.4里被反复考。

408 的段式虚拟存储器计算题极少。 它主要以概念对比的形式出现——与页式比、与段页式比。

对照速查

页式段式
划分依据固定长度逻辑结构,长度可变
地址维度一维二维
物理地址拼接段基址 + 偏移(加法)
越界检查不需要必须(查段长)
碎片内部碎片外部碎片
对程序员透明可见
共享与保护可以,但无逻辑含义方便,粒度有逻辑含义
表项字段物理页号 + 控制位段长 + 段基址 + 控制位

考点

  • 段按逻辑结构划分,长度可变;地址是二维的
  • 物理地址 = 段基址 + 段内偏移(加法),页式是拼接
  • 段表项必须有段长,用于越界检查;页式不需要
  • 段式产生外部碎片,页式产生内部碎片
  • 分段对程序员可见,分页透明
  • 段式便于共享和保护,因为段是一个完整的逻辑模块

链接