x86上操作系统怎么保证每个进程可以寻址4G空间且相互隔离

x86上操作系统如何保证每个进程可以寻址4G空间且相互隔离?

在操作系统上,每个进程是可以寻址4G空间的而且相互隔离。但是分析CPU的寻址机制,有如下疑问:

对于 x86,考虑 CPU分段机制,寻址时先将逻辑地址转换为线性地址

1)逻辑地址为 段选择符:段内偏移. 段选择符对应一个段描述符,对于每个段描述符而言,段限长最大可以设置为4G
考虑极端情况,也就是使用一个描述符就可以寻址4G空间。

2)x86上线性地址空间 为4G

这就意味着,使用一个描述符寻址,在最极端情况下可以映射满整个线性地址空间。 而一个任务如果想寻址4G空间的话,必定是段基址为0,段限长为4G

假设目前有3个任务,各自都使用自己的描述符来寻址。如果每个任务都能寻址4G空间的话,必定这三个任务的段基址都为0,段限长都为4G 这样的话,这3个任务映射的线性地址必定完全重合,无法隔离。

那如何保证每个任务可以寻址4G空间且相互隔离?
貌似不太可能,但是实际系统中比如windows上的确可以运行多个进程,而每个进程寻址4G空间且相互隔离。
是理解有误?还是操作系统的进程地址空间根本就不是使用CPU分段机制来实现的?


PS:不管有没有启用分页机制都无关紧要,因为分页机制只是将线性地址进行变化,此时已经与描述符无关,也就是与任务无关。也就是即使是不同的任务,只要线性地址相同,经分页机制映射到的物理地址必定也是相同的。



------解决方案--------------------
用页表的属性来隔离,建议察看一下PM编程。
------解决方案--------------------
64位段描述符的第0~15位及第48~51位构成了段界限的20位地址,段描述符的第55位为粒度标志,当粒度标志为0时,地址的值每相差1表示1字节,最大段界限值(当20位段界限值全为1时)为1M,当粒度标志为1时,地址的值每相差1表示4K,最大段界限(当20位段界限值全为1时)为4G,但段界限值一般都远小于4G,每个进程的段界限都由段描述符来分配。每个进程都只能寻址由段描述符分配给自身的地址空间,任何进程都不能超出段描述符的界限,一旦哪个进程使用了超出自身段界限的地址空间,进程立即被中止,处理器产生一个通用保护异常信号。所以,“每个进程可以寻址4G空间”本身就是错误的,实际上每个进程只能寻址自身的空间,4G是对整个系统来说的,而不是对单个进程。
------解决方案--------------------
这个就涉及到了x86处理器保护模式下的寻址了
在保护模式下,地址都是虚拟地址,也叫线性地址,为32位,因此每个程序都可以拥有32位的虚拟地址空间,也就是可以寻址2^32B=4GB。

启用分页机制以后,每个进程都有自己的一个全局描述符表(GDT),一个局部描述符表(LDT),这些表保存着本进程所有的虚拟地址映射信息。在这种架构下,每个进程的虚拟地址的每一页都可以映射到不同的物理地址。

想知道具体的实现,可以看一下 Windows Internals第四版,貌似第五版也出来了

探讨
在操作系统上,每个进程是可以寻址4G空间的而且相互隔离。但是分析CPU的寻址机制,有如下疑问:

对于 x86,考虑 CPU分段机制,寻址时先将逻辑地址转换为线性地址

1)逻辑地址为 段选择符:段内偏移. 段选择符对应一个段描述符,对于每个段描述符而言,段限长最大可以设置为4G
考虑极端情况,也就是使用一个描述符就可以寻址4G空间。

2)x86上线性地址空间 为4G

这就意……

------解决方案--------------------
我同意!
但是有一点儿,有点儿迷惑的。假如A,B都映射到同一个线性地址。
先运行A,A的该段内存加载到了物理内存。这时切换到B,也要访问该内存,则需要重新加载,我现在有如下问题:
1、凭什么确定重新加载?LDT的present标志?
2、原来A加载的该段内存内容怎么处理?写回硬盘吗?怎么处理A的LDT present标志?
3、怎样确保再切回A的时候,该段内存再次重新加载呢?
借楼主的地盘同问。

探讨

这个就涉及到了x86处理器保护模式下的寻址了
在保护模式下,地址都是虚拟地址,也叫线性地址,为32位,因此每个程序都可以拥有32位的虚拟地址空间,也就是可以寻址2^32B=4GB。

启用分页机制以后,每个进程都有自己的一个全局描述符表(GDT),一个局部描述符表(LDT),这些表保存着本进程所有的虚拟地址映射信息。在这种架构下,每个进程的虚拟地址的每一页都可以映射到不同的物理地址。

……

------解决方案--------------------
探讨
每个进程是可以寻址4G空间的而且相互隔离。但是分析CPU的寻址机制,有如下疑问:

------解决方案--------------------
你说的这个我认同。
能否解释一下,切换的时候,需要做那些操作?应该不只是改变CR3吧?原来进程的内存需要怎么操作才能保证下次再切换回来的时候可以顺利执行?

探讨

方法可能会有很多种,我可以给出一种。以下问题我针对的硬件平台是IA32。这里有一个cr3的控制寄存器,它保存了页目录的基址。如果我们让每一个进程都有自己的页目录,那么我们就可以让每个进程可以拥有自己的4G空间。只不过在实现进程切换时我们要把这个cr3中的内容又换成相应进程的页目录即可。简单吧,如果有困惑,我建议你去看看《IA32 系统编程》这本书吧。