2016-06-27 71 views
2

我有一个字符驱动程序,其中我添加的接口函数之一是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 

你能帮我吗?

回答

1

快速回答:您必须使用do_munmap()从用户进程中取消映射页面。
virt_to_phys()不能完成这项工作。它被内核用来将 内核虚拟地址(不是用户虚拟地址)转换为物理地址。

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

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

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

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

希望这有助于!

+0

谢谢你的帮助。你可以请,如果可能的话,指导我如何找到适当的VMA结构?正如我所看到的,在mm_strct中有一个名为mm_rb的红黑树,其中包含vma结构。那么如何访问进程的mm_struct,以及如何在此树中搜索? –

+0

嗨,这是通过do_munmap() - > find_vma()完成的,你可以看看这个链接的源代码。 http://lxr.free-electrons.com/source/mm/mmap.c#L2411 – Lin