内核如何寻址交换分区\文件上的交换内存页?

dir*_*obs 4 kernel swap virtual-memory linux-kernel memory-management

交换分区不包含结构化文件系统。内核不需要它,因为它在标记为交换区的分区上存储了内存页。由于交换区中可能有多个内存页面,当进程请求将其页面加载到内存中时,内核如何定位每个页面。让我们解释更多,查看 Devuan OS 中交换分区的标题:

#define SWAP_UUID_LENGTH 16
#define SWAP_LABEL_LENGTH 16
struct swap_header_v1_2 {
    char          bootbits[1024];    /* Space for disklabel etc. */
    unsigned int  version;
    unsigned int  last_page;
    unsigned int  nr_badpages;
    unsigned char uuid[SWAP_UUID_LENGTH];
    char          volume_name[SWAP_LABEL_LENGTH];
    unsigned int  padding[117];
    unsigned int  badpages[1];
};
Run Code Online (Sandbox Code Playgroud)

因此,当mkswap对分区执行命令时,这就是放置在该分区上的内容,即交换标头。

现在,让我们假设一个场景,进程 A 的内存页面被交换,因此交换区域中有一个内存页面。当然,交换区中可能有很多内存页。现在,进程 A 需要访问被交换的内存页。进程 A 告诉内核,我可以交换内存页吗?内核说:当然是我亲爱的朋友。内核会在交换分区中寻找进程 A 的内存页。由于交换分区不是一个复杂的结构(不是文件系统),内核如何知道如何在交换分区中定位进程 A 的特定内存页面。

也许内核在某处存储了那些交换页面的扇区地址,所以当一个进程请求它的内存页面时,内核知道在交换分区中查找的位置,从分区读取内存页面并将其加载到内存中。

Ste*_*itt 6

Swap 仅在给定的引导期间有效,因此所有跟踪信息都保存在内存中。页面进出完全由内核处理,对进程透明。基本上,内存被分成页,在页表中跟踪;这些是由每个 CPU 架构定义的结构。当页面被换出时,内核将其标记为无效;因此,下次任何尝试访问该页面时,CPU 都会出错,这将导致调用内核中的处理程序;恢复页面的内容是这个处理程序的责任。

在 Linux 中,有一个swap_info描述每个交换设备或文件的结构。在该结构中,aswap_map将内存页映射到交换设备或文件中的块。当一个页面被换出时,内核将swap_info索引和swap_map偏移量存储在相应的页表条目中,这允许它在必要时在磁盘上找到该页面。(所有支持的架构都在其页表中为此提供了足够的空间,但存在限制——例如,可用空间意味着 Linux 在 x86 上最多可以管理 64GiB 的交换。)

您可以在Mel Gorman 的《了解 Linux 虚拟内存管理器》的“交换管理”一章中找到所有这些的更详细描述。