操作系统基础32-内存管理-分段
2020-12-20 03:27·重学IT的老猫
通过前面的学习我们知道,用户的内存视图与实际的物理内存不一样。这同样适用于程序员的内存视图。
事实上,对操作系统和程序员来说,按物理性质来处理内存是不方便的。如果硬件可以提供内存机制,以便将程序员的内存视图映射到实际的物理内存,系统将有更多的自由来管理内存,而程序员将有一个更自然的编程环境。分段提供了这种机制。
分段的基本方法
在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。
每个段都有自己的名字。为了实现简单起见,通常可用一个段号来代替段名,每个段都从0开始编址,并采用一段连续的地址空间。段的长度由相应的逻辑信息组的长度决定,因而各段长度不等。整个作业的地址空间由于是分成多个段,因而是二维的,亦即,其逻辑地址由段号(段名)和段内地址所组成。
因此,逻辑地址由有序对组成: <段号,偏移>
通常,在编译用户程序时,编译器会根据输入程序来自动构造段。 一个C编译器可能会创建如下段:
- 代码
- 全局变量
- 堆(内存从堆上分配)
- 每个线程使用的栈
- 标准的C库
在编译时链接的库可能分配不同的段。加载程序会装入所有这些段,并为它们分配段号。
分段硬件
虽然用户现在能够通过二维地址来引用程序内的对象,但是实际物理内存仍然是一维的字节序列。因此,我们应定义一个实现方式,以便映射用户定义的二维地址到一维物理地址。这个地址是通过段表来实现的。
段表的每个条目都有段基地址和段界限。段基地址包含该段在内存中的开始物理地址,而段界限指定该段的长度。
分段硬件
段表的使用如上图所示。每个逻辑地址由两部分组成:段号 s 和段偏移 d。
段号用作段表的索引,逻辑地址的偏移d应位于0和段界限之间。如果不是这样,那么会陷入操作系统中(逻辑地址试图访问段的外面)。如果偏移d合法,那么就与基地址相加而得到所需字节的物理内存地址。因此,段表实际上是基址寄存器值和界限寄存器值的对的数组。
分段的例子
例如,假设如上图分段的例子所示的情况。有5个段,按0~4来编号。各段按如图所示来存储。每个段都在段表中有一个条目,它包括段在物理内存内的开始地址(基地址)和该段的长度(界限)。 如,段2为400字节长,开始于位置4300。因此,对段2字节53的引用映射成位置4300 + 53 = 4353。对段3字节852的引用映射成位置3200(段3基地址)+ 852 = 4052。对段0字节1222的引用会陷入操作系统,这是由于该段仅为1000字节长。