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第四版,貌似第五版也出来了