当物理页面从内存中被驱逐时,如何知道页面table的索引来更新PTE?

How to know the index of page table to update PTE when the physical page is evicted from the memory?

如果OS发现要逐出的页框,

它必须查找页面 table(可能通过特殊寄存器)并使页面 table 条目无效。

问题是,虽然我们可以从虚拟地址索引页面 table 条目(在页面 table 中),

我们无法从物理地址索引页 table 条目(在页 table 中)。

当页面被逐出时,OS如何找到要更新的页面table的索引?

此外,当页面被驱逐到辅助存储时,页面是否总是被驱逐到相同的

辅助存储的位置? (或者只是在驱逐时获得免费的space被驱逐?)

这个问题对很多 OS 理论都有影响。为了更好地理解,您可以查看 x86 Linux 以及此架构上的 OS 是如何工作的。

这里有一个简短的版本供参考。每个交换区都有一个swap_info_struct。每个 swap_info_struct 都存储在一个名为 swap_info 的静态定义列表中,该列表有 32 个条目。

 64 struct swap_info_struct {
 65     unsigned int flags;
 66     kdev_t swap_device;
 67     spinlock_t sdev_lock;
 68     struct dentry * swap_file;
 69     struct vfsmount *swap_vfsmnt;
 70     unsigned short * swap_map;
 71     unsigned int lowest_bit;
 72     unsigned int highest_bit;
 73     unsigned int cluster_next;
 74     unsigned int cluster_nr;
 75     int prio;
 76     int pages;
 77     unsigned long max;
 78     int next;
 79 };

每个交换区被分成页面大小的槽。在 x86 上意味着 4096 字节。第一个槽用于存储交换区的信息(header)。其余的插槽是实际换出的页面。交换区可以是文件或磁盘上的分区。

当页面被逐出时,对应于该页面的页面 table 条目将更改为 swp_entry_t 结构。该结构包含一个具有多种含义的值。位 0 保留用于设置为 0 的页面存在标志,以便在程序尝试读取该数据时发生页面错误。位 1-6 用于 swap_info 数组中的索引(保存被逐出页面的实际交换区域)。位 8-31 是页面所在的交换区中的偏移量。它有 24 位,将交换区大小限制为 64GB(页面为 4KB)。

 16 typedef struct {
 17     unsigned long val;
 18 } swp_entry_t;

有关详细信息,请阅读以下内容https://www.kernel.org/doc/gorman/html/understand/understand014.html

每个进程都有一个 task_struct 来保存该进程信息。 task_struct 包含一个名为 mm 的成员,它本身是一个包含名为 pgd 的成员的结构。 pgd 是指向该进程第一级页面 table 的指针。通过取消引用 pgd,我们可以访问属于不同页面 tables 的数据。例如,如果您键入 *pgd,您将获得页面第一级的实际第一个条目 table。第一个条目是下一级页面底部的地址table。所以你基本上有一个指向下一级页面的指针table。也就是说,如果你写**pgd,你得到的是下一级页面的值table。你明白了,通过使用 pgd 我们可以访问所有页面 tables.

当发生页面错误时,它可能意味着一些事情,错误代码会被压入堆栈,以便 OS 可以确定导致页面错误的原因。如果该页面没有设置当前位,则可能意味着该页面已被逐出到辅助存储。然后 IP(程序计数器)将被压入堆栈以处理页面错误。 Linux 通过查看进程堆栈找到有问题的地址。一旦找到违规地址,它就会使用 pgd 指针访问实际页面 tables,然后换入被逐出的页面。

当一个页面被换出时,它会根据我不太了解的优先级方案存储到交换区域。当一个页面被换入时,它将被分配到新被逐出的页面所拥有的内存。因为如果页面被逐出,则意味着内存已满,因此要换入一个页面,您必须换出另一个页面。换入页面取代换出页面。