我正在讨论操作系统中的细分主题。
我了解到分段的概念之所以存在,是因为内存中加载的进程的地址空间中可能存在空闲空间。
我将尝试首先解释一些我从研究中理解的东西。如果有任何错误,请纠正我。
例如,如果不使用分段,这可能不是理想的情况
我有一个地址空间很小的进程,它被加载到内存中。由于进程地址空间可能不会放在物理内存的开头。我们需要一些机制来转换程序代码的地址(代码段,从哪里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 |---------------------|
那么现在如果处理器在执行代码指令时需要将虚拟内存地址转换为物理内存地址,它如何知道选择哪个基值,因为段表中可能有很多基值?
假设让我们说指令是更新一些堆栈变量..在这种情况下它将如何选择堆栈的基值?
那么物理内存地址=堆栈的基地址+指令中的虚拟内存地址?
除了外部碎片之外,分割的缺点是什么。
任何对分段//分页/虚拟化概念进行详细解释的外部链接都会非常有帮助。