如何使用页面错误处理程序映射页面? [英] How to map pages using the page fault handler?

查看:51
本文介绍了如何使用页面错误处理程序映射页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 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 the vma to current->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 using page_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆