【发布时间】:2014-11-28 10:41:38
【问题描述】:
我正在讨论操作系统中的细分主题。
我了解到分段的概念是由于内存中加载的进程的地址空间中可能存在的空闲空间而产生的。
我将尝试首先解释一些我从研究中理解的东西。如果有任何错误,请纠正我。
比如说,如果没有使用分段,那可能不是理想的情况
我有一个地址空间很小的进程,它被加载到内存中。由于进程地址空间可能不会放在物理内存的开头。我们需要一些机制来转换程序代码(代码段)的地址,从执行 PC 指向的指令的位置)到实际的物理内存地址。因此,我们为此使用硬件寄存器(MMU)来维护正在运行的进程的基值和绑定值。基值是放置进程的物理内存的起始地址,绑定是运行进程的总大小或正在运行的进程的最后地址。由于MMU是全局的,我们需要在上下文切换时保存基值/绑定值。
所以这里physical memory address = virtual memory address + base;
现在假设我们有一个地址空间很大的进程。我们需要一些像分段这样的机制来更好地利用空闲空间,因为进程地址空间可能在堆和堆栈或代码和堆之间包含大量空闲空间。
对于分段,我们为每个进程维护一个分段表(需要在上下文切换时将表存储在 PCB 中)。
在分段中,我们为正在运行的进程地址空间的每个逻辑段维护基本/绑定值。因此,理想情况下,我们为每个代码、堆栈和堆段维护基本/绑定值,并将这些值存储在段表中。
所以段表应该有点像这样..
Segment | Base | Bounds
---------------------------
Code | 16K | 1K
Heap | 28K | 1K
Stack | 20K | 2K
物理内存可能看起来像这样..
0 |---------------------|
| OS |
| |
....
| |
| |
| |
16K |---------------------|
| (program code) |
| |
17K |---------------------|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxx free xxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
20K |---------------------|
| |
| |
| (stack) |
| |
22K |---------------------|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxx free xxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
28K |---------------------|
| |
| (heap) |
29K |---------------------|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxx free xxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxx|
32K |---------------------|
那么现在如果处理器在执行代码指令时需要将虚拟内存地址转换为物理内存地址,它如何知道选择哪个基值,因为段表中可能有很多基值?
假设指令是更新某个堆栈变量..在这种情况下它将如何选择堆栈的基值?
这么说物理内存地址=栈的基地址+指令中的虚拟内存地址?
以及除了外部碎片之外,分割的缺点是什么。
任何详细解释分段//分页/虚拟化概念的外部链接都会非常有帮助。
【问题讨论】:
-
细分是一个杂项。它一直是一个kludge。如果您想了解内存管理(尤其是在英特尔终于放弃了 64 位模式的分段之后),我建议您了解虚拟内存系统系统如何在没有分段的情况下工作。
-
这个问题似乎是题外话,因为它是关于计算机架构设计和实现,而不是编程。如果您有一个无法运行的程序,欢迎您在此处发布。或许cs.stackexchange.com 会更适合这类问题。
标签: operating-system memory-address virtual-memory memory-segmentation