在单核计算机上,一次执行一个线程。在每个上下文切换上,调度程序检查要调度的新线程是否与前一个线程处于同一进程中。如果是这样,则不需要对MMU(页面表)进行任何操作。在另一种情况下,需要使用新的流程页表更新页面表。
我想知道多核计算机上是怎么发生的。我想每个核心上都有一个专用的MMU,如果同一进程的两个线程同时在2个核心上运行,则每个核心的MMU只需引用相同的页面表。这是真的 ?你能指点我对这个问题的好的参考吗?
答案 0 :(得分:15)
看看这个计划。这是Corei7 cpu上单核中所有内容的高级视图。这张照片取自计算机系统:程序员的视角,布莱恩特和哈拉龙。您可以访问here第9.21节中的图表。
答案 1 :(得分:5)
例如,在ARM上,顶层(Linux中使用的 PGD 或页面全局目录名称)覆盖1MB的地址空间。在简单系统中,您可以以1MB的部分进行映射。但是,这通常指向第二级表( PTE 或页表条目)。
有效实现多CPU的一种方法是为每个CPU设置一个单独的顶级 PGD 。操作系统代码和数据在核心之间保持一致。每个核心都有自己的TLB和L1缓存; L2 / L3缓存可能是共享的,也可能不是。数据/代码缓存的维护取决于它们是VIVT还是VIPT,但这是一个副作用,不应影响MMU和多核的使用。
第二级页面表的进程或用户部分对于进程保持不变;否则它们将具有不同的内存,或者您需要同步冗余表。当各个核心运行不同的进程时,它们可能具有不同的第二级页表(不同的顶级页表指针)。如果它是多线程的,并且在两个CPU上运行,则顶级表可以包含该进程的相同的第二级页表条目。事实上,当两个CPU运行相同的进程时,整个顶级页表可能相同(但内存不同)。如果使用MMU实现线程本地数据,则单个条目可能不同。但是,由于TLB和缓存问题(刷新/一致性),线程本地数据通常以其他方式实现。
下图可能有所帮助。图中的CPU,PGD和PTE条目有点像指针。
虚线是与MMU运行不同进程和相同进程(多线程情况)之间的唯一区别;它是从CPU2 PGD到过程B PTE或第二级页表的实线的替代。内核始终是一个多线程CPU应用程序。
当翻译虚拟地址时,不同的位部分是每个表的索引。如果TLB中没有虚拟地址,则CPU必须执行表行走(并获取不同的表存储器)。因此,对进程内存的单次读取将导致三次内存访问(如果TLB不存在)。
内核代码/数据的访问权限明显不同。事实上,可能会有其他问题,例如设备内存等。但是,我认为图表应该明确MMU如何设法保持多线程内存不变。
第二级表中的条目完全有可能每个线程不同。但是,这会在同一CPU上切换线程时产生成本,因此通常会映射所有“线程本地”的数据,并使用其他一些方法来选择数据。通常,线程本地数据是通过指针或索引寄存器(每个CPU特殊)找到的,该寄存器映射/指向“进程”或用户存储器内的数据。 “线程本地数据”不与其他线程隔离,因此如果在一个线程中有内存覆盖,则可能会杀死另一个线程数据。
答案 2 :(得分:1)
到目前为止,答案似乎并不知道Translation Lookaside Buffer(TLB)的存在,这是MMU将进程使用的虚拟地址转换为物理内存地址的方式。
请注意,这些天TLB本身是一个复杂的野兽,有多个caching级别。就像CPU的常规RAM缓存(L1-L3)一样,您不一定会期望它在任何给定时刻的状态仅包含有关当前正在运行的进程的信息,而是根据需要随意移动;请参阅维基百科页面的Context Switch部分。
在SMP上,所有处理器的TLB都需要保持系统页表的一致视图。有关处理它的一种方法,请参见this section of the linux kernel book。
答案 3 :(得分:0)
AFAIK每个物理处理器只有一个MMU,至少在SMP系统中,因此所有内核共享一个MMU。
在NUMA系统中,每个核心都有一个单独的MMU,因为每个核心都有自己的私有内存。
答案 4 :(得分:0)
在ARMv8中,表基地址寄存器具有CnP位以支持内部可共享域中的分片TLB: enter image description here
答案 5 :(得分:-1)
关于每个处理器的MMU问题,可能有几个。假设每个MMU将增加额外的内存带宽。如果DDR3-12800内存允许在具有一个MMU的处理器上每秒进行1600兆传输,则理论上允许6400一个就可以允许6400.将带宽保护到可用内核可能是一个壮举。在此过程中,所宣传的带宽将被削减相当多。
处理器上的MMU数量与其上的核心数无关。显而易见的例子是AMD的16核CPU,他们肯定没有16 MMU。另一方面,双核处理器可能有两个MMU。或者只是一个。还是三个?
修改强>
也许我把MMU与频道混淆了?