【问题标题】:How does "get_user_pages" work (For linux driver)“get_user_pages”如何工作(适用于 linux 驱动程序)
【发布时间】:2016-07-20 04:11:52
【问题描述】:

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

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

为此,我们有get_user_pages,其完整定义如下:

int get_user_pages(struct task_struct * tsk,  
    struct mm_struct * mm,  
    unsigned long start,  
    int nr_pages,  
    int write,  
    int force,  
    struct page ** pages,  
    struct vm_area_struct ** vmas);

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

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

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

那么三个问题,谢谢提前。

【问题讨论】:

  • 使用posix_memalign() 你确定它是对齐的,或者你在malloc()/mmap() MAP_ANONYMOUS 之后检查它。如果没有,您可以过度分配并对齐指针。 (保留原来的指针释放内存)

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


【解决方案1】:

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

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

如果你想固定 4 个页面,struct page *pages[4]; 就足够了。

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

这个参数应该指向你的用户进程拥有的内存(比如malloc之后)。

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

我认为你可以使用getpagesize 函数来做到这一点。

我认为这篇博文:"get_user_pages example" 可能会对您有所帮助。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-13
  • 1970-01-01
  • 2013-12-21
  • 2016-08-15
  • 2012-11-02
  • 1970-01-01
  • 2017-04-08
相关资源
最近更新 更多