一个疑问:CPU 运行两个 test.out 进程,使用的是各自进程的虚拟地址,那 CPU 是如何识别出当前这个虚拟地址是属于哪个进程的?带着这个疑问,我们一起开始今天的探索
如上图,CPU 是如何知道 0x4785c4 这个地址,是属于左边这个进程的(右边进程也有可能使用这个地址)?如何知道 0x4805c4 这个地址是属于右边这个进程的(左边进程也有可能使用这个地址)?
linux 中使用虚拟地址,每个进程都有独立的用户空间虚拟地址以及共用的内核空间虚拟地址。
以 32 位系统为例,每个进程都有 0x00000000~0xbfffffff 范围的用户空间虚拟地址以及共用的 0xc0000000~0xffffffff 内核空间虚拟地址。
假设 linux 系统中运行了两个进程 P1 和 P2,两个进程都使用了 0x00001000 这个用户空间虚拟地址。那么,CPU 是如何识别这两个相同的用户空间虚拟地址属于哪个进程的呢?又是如何将这两个相同的用户空间虚拟地址对应到不同的物理内存地址上的呢?
MMU(内存管理单元)是一种硬件设备,用于处理虚拟地址和物理地址之间的转换。它与操作系统紧密合作,以对不同进程的虚拟地址进行正确的映射。
在 Linux 中,MMU 使用页表来将虚拟地址转换为物理地址。每个进程都有自己的页表,用于将其虚拟地址映射到不同的物理地址。当 CPU 访问一个虚拟地址时,MMU 使用当前活动的页表来查找对应的物理地址。
操作系统在进程切换时,会更新 MMU 中的页表,将当前进程的页表加载到 MMU 中。这样,当 CPU 执行不同进程的指令时,MMU 就能根据相应的页表进行正确的地址转换。这样,不同进程的相同虚拟地址就可以映射到不同的物理地址,保证了进程间的地址隔离和安全性。
CPU 在执行用户空间程序时,使用的是虚拟地址,CPU 也不知道这个虚拟地址是属于哪个进程的,它只管将这个虚拟地址发送给 MMU。
关键点在 MMU,CPU 执行哪个进程,MMU 中的页表寄存器(PTR )指向的就是哪个进程的页表。使用该进程的页表,查找出来的当然是该进程对应的物理内存地址。