【问题标题】:Virtual to Kernel logical address虚拟到内核逻辑地址
【发布时间】:2016-06-27 08:41:35
【问题描述】:

我有一个 char 驱动程序,其中我添加的接口函数之一是alloc_contig(int order),其中 order 是所需数量的 4K 页的 log2。 此函数分配连续的物理内存并使用remap_pfn_range 函数将其映射为用户空间使用。 我正在尝试编写释放此内存的函数dealloc_contig(va) 现在在内核中,我有用户提供的免费虚拟地址,我需要获取底层物理地址,所以我尝试使用virt_to_phys,但它没有给我想要的地址。 日志:

//allocating
page address is ffff880868764000 //allocated using alloc_pages
//deallocating
virtual address from user 7f4c7e095000
when converted to PA using virt_to_phys got f74c7e095000 instead of ffff880868764000 

你能帮帮我吗?

【问题讨论】:

    标签: c linux memory linux-kernel linux-device-driver


    【解决方案1】:

    快速回答:您必须使用 do_munmap() 从用户进程中取消映射页面。
    virt_to_phys() 可以不要做这个工作。内核使用它来翻译 内核虚拟地址(不是用户虚拟地址)到物理地址。

    用户空间内存由 vma 区域组织。(struct vm_area_struct *vma)。 它们可以在每个进程的 struct mm_struct 下找到。流程 拥有自己的 mm_structs,以便不同进程的相同虚拟地址映射到不同的物理地址。

    您需要做的是,获取虚拟地址。然后,在内核空间中,您需要 找出这个地址属于哪个vma,然后取消映射地址范围 从 vma 回收页面。(这是 do_munmap() 所做的。)。

    还有一点值得一提的是,因为进程有自己的 mm_struct,因此也有自己的 vma 区域。 do_munmap() 必须在“正确”的用户进程上下文中调用,否则会得到错误的 mm_struct。

    总结一下步骤:
    1.映射了区域调用的用户进程 你的接口释放虚拟地址。 2.系统调用内核空间(这是在您的用户进程的上下文中)。您的驱动程序处理程序调用 do_munmap() 到 取消映射虚拟地址。
    3.您的驱动程序释放页面。

    希望这会有所帮助!

    【讨论】:

    • 感谢您的帮助。如果可能的话,您能否指导我如何找到合适的 vma 结构?正如我所看到的,在 mm_strct 中有一个名为 mm_rb 的红黑树,其中包含 vma 结构。那么如何访问进程的 mm_struct 以及如何在这棵树中进行搜索呢?
    • 您好,这是通过do_munmap() -->find_vma()完成的,您可以在此链接查看源代码。 lxr.free-electrons.com/source/mm/mmap.c#L2411
    猜你喜欢
    • 2012-02-01
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 2011-06-17
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多