“get_user_pages”如何工作(对于linux驱动程序)

时间:2016-03-31 15:42:42

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

使用Linux PCI驱动程序,现在我正在尝试使用scatter / gather编写DMA代码。

目前,我已经了解到要直接从用户空间访问DMA数据,我们需要将用户空间页面固定到内核空间。

要做到这一点,我们有get_user_pages,其完整定义如下:

  

int get_user_pages(struct task_struct * tsk,
  struct mm_struct * mm,
  无条件的长启动,
  int nr_pages,
  int写,
  int force,
  struct page ** pages,
  struct vm_area_struct ** vmas);

我的第一个问题是struct page ** pages。在调用kcalloc之前,我们需要为pages分配内存(使用get_user_pages替换。)

我的第二个问题是关于unsigned long start,在手册页上,它显示“起始用户地址”,这是否意味着,如果我在用户空间中声明指针,如int *p,则“起始用户地址“我应该传递给内核空间是p

我的第三个问题也是关于unsigned long start,如果我在第二个问题中理解正确,那么我们如何才能确保这个地址正好在页面的开头?

所以有三个问题,谢谢你的进步。

1 个答案:

答案 0 :(得分:3)

  

我的第一个问题是关于struct page **页面。在调用get_user_pages之前,我们需要为页面分配内存(例如使用kcalloc)吗?

你可以,但这不是强制性的,数组足够(它的大小取决于nr_pages

如果要固定4页,struct page *pages[4];就够了。

  

我的第二个问题是关于无符号长启动,在手册页上,它显示“启动用户地址”,这是否意味着,如果我声明一个类似int * p的指针,那么“起始用户地址”我应该通过到内核​​空间是p?

此参数应指向您的用户进程拥有的内存(例如在malloc之后)。

  

我的第三个问题也是关于unsigned long start,如果我在第二个问题中理解正确,那么我们如何确保这个地址正好在页面的开头?

我认为你可以使用getpagesize函数来完成它。

我认为此博客文章:"get_user_pages example"可能对您有帮助。