You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

64位Linux中用户进程页面换入换出时虚拟地址归属疑问

用户进程页面换入/换出时的虚拟地址归属(64位Linux)

核心结论:用户进程的页面本身的虚拟地址始终属于用户空间,但内核在处理换入/换出操作时,会使用内核空间的虚拟地址来访问对应的物理页。

换入场景(对应linux-6.5.1/mm/memory.c代码)

当发生缺页需要换入页面时,mm_account_fault函数中的address参数是触发缺页的用户态虚拟地址,完全落在你给出的用户态地址范围(0x0000000000000000-0x00007FFFFFFFFFFF)内。
virt_to_pfn(address)通过进程的页表将用户虚拟地址转换为物理页帧号(PFN),内核完成页换入后,会把这个用户虚拟地址和物理页重新建立映射,用户进程后续访问该地址时,依然使用的是用户空间的虚拟地址。

对应的代码片段:

mm_account_fault()
    if (major) {
        struct major_page_fault_hash_entry *temp = NULL;
        unsigned long pfn = virt_to_pfn(address);
        printk("[%lu][i][%lu]", pfn, address);
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
    }

其中printk输出的第二个%lu就是用户空间的虚拟地址,对应换入操作的目标用户地址。

换出场景(对应linux-6.5.1/mm/swap_state.c代码)

当页面被换出到交换分区时,内核需要直接访问物理页的内容。page_to_virt(current_page)返回的是内核空间的虚拟地址,落在你给出的内核态地址范围(0xFFFF800000000000-0xFFFFFFFFFFFFFFFF)内——这是因为内核拥有所有物理页的线性映射,通过内核虚拟地址可以直接操作物理页。
但这个内核虚拟地址只是内核操作页的临时地址,用户进程对该页的认知始终是原来的用户空间虚拟地址,换出后用户访问该地址会触发缺页,内核再从交换分区换入并重新建立用户虚拟地址到物理页的映射。

对应的代码片段:

bool add_to_swap(struct folio *folio)
    long pages_number = folio_nr_pages(folio);
    unsigned long start_pfn = folio_pfn(folio);

    for (int i = 0; i < pages_number; i++) {
        struct page *current_page = pfn_to_page(start_pfn + i);
        unsigned long current_virt_addr = (unsigned long)page_to_virt(current_page);
        printk("[%lu][o][%lu]\n",start_pfn + i, current_virt_addr);
    }

这里printk输出的第二个%lu就是内核空间的虚拟地址,用于内核写入交换分区时访问物理页。


内容的提问来源于stack exchange,提问作者Mia8Cew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 09:40:03