目录
- 一个生动的比喻:一本书的章节
- “段”的技术性定义和核心特征
- “段”在内存中是如何存在的?
- 总结
简单来说,“段”就是一个程序在逻辑上的一个完整组成部分。
它不是物理上硬性划分的内存块,而是按程序的逻辑意义自然形成的一个内存区域。
一个生动的比喻:一本书的章节
想象一下,你写的一本书就是一个完整的“程序”。
- 整本书 = 整个程序
- 每一个章节 = 一个“段”
比如,你的书可能有:
- 第一章:引言 (这是一个段)
- 第二章:核心理论 (这是另一个段)
- 第三章:实验数据 (又一个段)
- 附录A (也是一个段)
“段式存储”就像是在管理这本书。 它不要求所有章节必须连续地印刷在同一张巨大的纸上。相反,它允许:
- “引言”章印在A打印店的某几页上。
- “核心理论”章印在B打印店的另几页上。
- 只需要一个“目录”(段表)来记录每一章存放在哪里,以及它有多长。
当你阅读时,你通过“目录”来定位章节,而不是死记硬背“第105页是哪一章?”。
“段”的技术性定义和核心特征
在计算机科学中,一个“段”通常指以下内容之一:
- 代码段:存放程序执行指令的部分。通常是只读的。
- 数据段:存放已初始化的全局变量和静态变量。
- BSS段:存放未初始化的全局变量和静态变量。
- 堆段:存放程序运行时动态分配的内存(如
malloc/new出来的数据)。 - 栈段:存放函数调用时的局部变量、返回地址等。
“段”的核心特征:
| 特征 | 解释 | 与“页”的对比 |
|---|---|---|
| 逻辑性 | 按意义划分。程序员和编译器知道代码段、数据段的存在。 | 物理性。页是固定大小的内存块,对程序透明,程序不知道“页”的存在。 |
| 可变长度 | 段的大小由其内容决定。代码段可能很大,数据段可能很小。 | 固定大小。通常是4KB或2MB,与内容无关。 |
| 独立性与保护 | 每个段可以被独立设置访问权限(如:代码段只读、数据段可读可写)。一个指针错误不会轻易破坏代码段。 | 保护也在页级别,但它是基于物理块的,而非逻辑单元。 |
| 可见性 | 在段式管理中,程序的地址空间是二维的,由(段号, 段内偏移)组成。 |
在纯页式管理中,程序的地址空间是一维的线性地址。 |
“段”在内存中是如何存在的?
程序在运行时,它的不同段并不需要连续地存放在物理内存中。操作系统通过一个叫做 “段表” 的数据结构来管理它们。
过程如下:
- 编译器/程序员将程序划分为多个逻辑段。
- 当程序被加载运行时,操作系统为每个段在物理内存中寻找一块足够大的、连续的空间(注意:是段内连续,段与段之间可以不连续)。
- 操作系统创建一个 “段表” 。段表的每个条目描述一个段,主要包括:
- 段号:段的唯一标识。
- 基址:这个段在物理内存中的起始地址。
- 段长:这个段有多大。
- 访问权限:可读、可写、可执行。
- 当CPU要访问一个内存地址时(比如
段号2,偏移量500),它首先去查段表,找到段号2的基址和段长。- 检查:偏移量500是否小于段长?本次操作(读/写)是否符合访问权限?
- 转换:如果检查通过,物理地址 = 基址 + 偏移量。
总结
所以,“段式存储”中的“段”,是一个具有完整逻辑意义的、长度可变的、作为独立单元被管理和保护的程序组成部分。
它反映了程序本来的样子,而不是强迫程序去适应内存的物理结构。这种“以人为本”(或者说“以程序为本”)的设计思想,使得它在满足方便编程、分段共享、分段保护、动态链接和动态增长等需求上,显得非常自然和高效。