Con*_* Li 6 c linux kernel-module linux-device-driver linux-kernel
在Linux PCI驱动程序上工作,现在我正尝试使用分散/聚集为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);
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是关于struct page ** pages。在这里,我们需要为分配内存(kcalloc用于ex),pages然后再调用get_user_pages吗?
我的第二个问题是关于unsigned long start,在手册页上说“起始用户地址”,这是否意味着,如果我在用户空间中声明一个指针,例如int *p,我应该传递给内核空间的“起始用户地址”是p?
我的第三个问题也与有关unsigned long start,如果我对第二个问题的理解正确,那么我们如何确保该地址恰好在页面的开头?
所以这三个问题,谢谢你的推进。
我的第一个问题是关于结构页**页的。在调用 get_user_pages 之前,我们是否需要为页面分配内存(例如使用 kcalloc)?
可以,但这不是强制性的,一个数组就足够了(它的大小取决于nr_pages)
如果你想固定 4 页struct page *pages[4];就足够了。
我的第二个问题是关于无符号长开始,在手册页上,它说“起始用户地址”,这是否意味着,如果我声明像 int *p 这样的指针,我应该将“起始用户地址”传递给内核空间是p?
此参数应指向用户进程拥有的内存(如 a 之后malloc)。
我的第三个问题也是关于无符号长开始,如果我在第二个问题中理解正确,那么我们如何确保这个地址恰好从页面的开头开始?
我认为你可以用功能来做到这一点getpagesize。
我认为这个博客条目:“get_user_pages example”可能对您有帮助。