如何使用页面错误处理程序映射页面? [英] How to map pages using the page fault handler?
问题描述
我想使用 struct vm_area_struct *
的pagefault处理程序将物理页面映射到用户空间.
I want to use the pagefault handler of my struct vm_area_struct *
to map a physical page to user space.
这是我的工作方式:
- 在模块初始化期间,我使用
alloc_page(GFP_USER)
全局分配了一个页面(我尝试了各种GFP). - 我创建了一个
struct vm_area_struct
,设置了一个自定义页面错误处理程序,并将vma
附加到current->mm
.
- I globally allocate a page using
alloc_page(GFP_USER)
during the module initialization (I tried various GFP). - I create a
struct vm_area_struct
, set a custom pagefault handler, and attach thevma
tocurrent->mm
.
发生页面错误时:
- 我将
vmf-> page
设置为我先前分配的页面,并返回0.
- I set
vmf->page
to the page I previously allocated and return 0.
结果是,发生页面错误后, vma
中的每个虚拟页面都应映射到同一物理页面.
The result is that every virtual page in the vma
should be mapped to the same physical page after a page fault.
但这是我注意到的:
- 当我从内核模块写入页面时,它会反映在我的用户空间程序中.
- 当我从用户空间写入页面时,在内核模块中看不到它.
- 当我在内核模块中使用
get_user_pages
来获取页面时(而不是使用全局变量),我得到的物理地址与全局页面变量的物理地址不同.我使用page_to_phys(page)
打印地址.写入此页面反映在我的用户空间程序中.
- When I write to the page from my kernel module, it's reflected in my user-space program.
- When I write to the page from my user-space, I don't see it from my kernel module.
- When I'm using
get_user_pages
in my kernel module to get the page (instead of using my global variable), I get a different physical address than the global page variable. I print the address usingpage_to_phys(page)
. Writing to this page is reflected in my user-space program.
所有这些都是在页面错误处理程序中完成的.
All of this is done in the page fault handler by the way.
如何解释这种奇怪的行为?
How can this curious behavior be explained?
要从内核空间访问页面,我正在使用 kmap_atomic
和 kunmap_atomic
.
To access the page from kernel space, I'm using kmap_atomic
and kunmap_atomic
.
推荐答案
这归因于写时复制机制.页面错误处理程序运行后,您在 vmf-> page
中返回的页面将复制到新分配的页面.这就是为什么您在用户空间中所做的更改未反映在内核模块中的原因.您尝试从内核中读取的页面不是在用户空间进程中真正映射的页面.
This is due to the copy-on-write mechanism.
After your page fault handler runs, the page you returned in vmf->page
is copied to a newly allocated page. This is why your changes in user-space are not reflected in your kernel module.
The page you were trying to read from in the kernel is not the one that was really mapped in your user-space process.
您可以参考 mm/memory.c
中的 do_cow_fault
函数.
这篇关于如何使用页面错误处理程序映射页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!