我正在使用由大页面支持的缓冲区的驱动程序,并且我发现大页面的顺序性存在一些问题。
mmap
在用户空间中,程序使用系统调用分配由大页面支持的大缓冲区。然后通过ioctl
调用将缓冲区传送给驱动程序。驱动程序使用该get_user_pages
函数来获取该缓冲区的内存地址。
这适用于 1 GB(1 个大页面)的缓冲区大小。get_user_pages
返回很多页面(HUGE_PAGE_SIZE / PAGE_SIZE
),但它们都是连续的,所以没有问题。我只是抓取第一页的地址page_address
并使用它。remap_pfn_range
当另一个程序mmap
在 char 设备上进行调用时,驱动程序还可以将该缓冲区映射回用户空间。
但是,当缓冲区由多个大页面支持时,事情会变得复杂。内核似乎可以返回一个由非顺序大页面支持的缓冲区。即,如果大页面池的布局是这样的
+------+------+------+------+
| HP 1 | HP 2 | HP 3 | HP 4 |
+------+------+------+------+
,可以通过保留 HP1 和 HP4 或 HP3 然后 HP2 来满足对大页面支持缓冲区的请求。这意味着当我get_user_pages
在最后一种情况下获得页面时,页面 0 的地址实际上是页面 262.144 (下一个大页面的头部)地址之后的 1 GB。
有什么方法可以按顺序访问这些页面?我尝试重新排序地址以找到较低的地址,以便我可以使用整个缓冲区(例如,如果内核给了我一个由 HP3 支持的缓冲区,HP2 我使用 HP2 的一个作为基地址),但似乎会打乱数据在用户空间中(该重新排序缓冲区中的偏移量 0 可能是用户空间缓冲区中的偏移量 1GB)。
TL;DR:给定 >1 个无序大页,有没有办法在 Linux 内核驱动程序中按顺序访问它们?
顺便说一句,我正在使用具有 3.8.0-29-generic 内核的 Linux 机器。