我读过:
流程切换是从一个流程到另一个流程的上下文切换。它涉及切换所有过程抽象和资源,以支持属于新过程的那些。最显着且昂贵的是,这意味着切换存储器地址空间。这包括内存地址,映射,页表和内核资源 - 相对昂贵的操作。
此外:
上下文是CPU的寄存器和程序计数器在任何时间点的内容。
可以稍微更详细地描述上下文切换,因为内核(即操作系统的核心)对CPU上的进程(包括线程)执行以下活动:(1)暂停一个进程的进程并在内存中的某个位置存储CPU进程的状态(即上下文),(2)从内存中检索下一个进程的上下文并将其恢复到CPU的寄存器中,以及(3)返回到程序计数器指示的位置(即,返回到进程被中断的代码行)以恢复进程。
由于 VAS 对于每个进程是独立的,并且大小可以达到4GB,因此在上下文情况下,进程的整个 VAS 会加载到CPU上下文中切换过程?
此外,由于每个进程都有单独的页表,如果进行上下文切换,页表是否也会进入CPU上下文?
如果不是,那么为什么进程上下文切换比线程上下文切换慢(线程共享相同的 VAS )?
答案 0 :(得分:4)
由于VAS对于每个进程是独立的,并且大小可以达到4GB,如果进程上下文切换,进程的整个VAS是否加载到CPU上下文中?
此外,由于每个进程都有单独的页表,在上下文切换的情况下,是否也在CPU上下文中购买了页表?
这些问题是相关的。您将一个虚拟地址空间替换为另一个 ,更改哪一组页表正在执行虚拟 - >线性翻译。这就是地址空间交换的完成方式。
让我们考虑一个非常简单的例子。
PP
的寄存器(可分页指针)初始化进程后,"交换虚拟地址空间"两者之间很简单。要加载P A 的地址空间,只需将T A 的地址放在PP
中,现在该过程"看到"内存在0x88000。同样地,对于P B ,T B 的地址,所以他将"看到"内存在0x99000。
在线程(同一进程)之间切换时,不需要更改虚拟地址空间(因为给定进程的所有线程共享相同的虚拟地址空间)。
当然还有其他需要交换的东西(比如CPU寄存器),但是对于这个讨论,我们只关心虚拟内存。
在x86 CPU上,CR3
寄存器是指向页表层次结构基础的指针。操作系统在交换进程时更改地址空间是该寄存器。
当然,它比这复杂得多。因为可能的虚拟地址空间太大(x86-32上为4 GiB,x86-64上为16 exabytes ),页面表本身会占用大量空间(每4个一个条目) KiB页面)。为了缓解这种情况,会在页表中添加额外的间接级别,这就是我将它们称为层次结构的原因。在x86-64上,有4个级别。
现在想象一下,如果CPU必须“走路”#34; 每个虚拟到物理转换的这些分页结构。从虚拟内存中单次读取将需要总共5次内存访问!这将非常缓慢。
输入Translation lookaside buffer或TLB。 TLB 缓存这些翻译,因此给定的虚拟到物理翻译只需要遍历一次页面表。之后,TLB会记住翻译,并且速度更快。 (当然TLB可以满员,但缓存驱逐是另一个故事)。
所以说P A 正在运行,并且内核突然在P B 的地址空间中交换。现在,所有这些缓存的虚拟到物理转换都不再适用于新的虚拟地址空间!这意味着我们需要刷新 TLB,或清除其所有条目。正因为如此,CPU必须再次进行慢速页面表行走,直到TLB缓存加热并且#34;试。
这就是为什么它被认为是昂贵的"交换虚拟地址空间。不是因为写CR3
很难,而是因为我们每次都会把TLB丢弃。