我有现有的代码,它接收一个struct page *
列表,并构建一个描述符表以与设备共享内存。该代码的上层当前期望使用vmalloc
或来自用户空间的缓冲区分配的缓冲区,并使用vmalloc_to_page
获取相应的struct page *
。
现在,上层需要处理各种类型的内存,而不仅仅是通过vmalloc
获得的内存。这可以是使用kmalloc
获得的缓冲区、内核线程堆栈内部的指针或其他我不知道的情况。我唯一的保证是,此上层调用者必须确保在该点映射了问题内存缓冲区(即,在此点上访问buffer [i]
对于所有0<=i<size
都是有效的)。 如何获取与任意指针相应的struct page*
?
将其放入伪代码中:
lower_layer(struct page*);
upper_layer(void *buffer, size_t size) {
for (addr = buffer & PAGE_MASK; addr <= buffer + size; addr += PAGE_SIZE) {
struct page *pg = vmalloc_to_page(addr);
lower_layer(pg);
}
}
现在我需要更改upper_layer
以适应任何有效的缓冲区(而不更改lower_layer
)。
我找到了virt_to_page
,Linux设备驱动程序指示其操作“逻辑地址,而不是来自vmalloc
或高内存的内存”。 此外,is_vmalloc_addr
测试地址是否来自vmalloc
,而virt_addr_valid
测试地址是否为有效虚拟地址(供virt_to_page
使用;这包括kmalloc(GFP_KERNEL)
和内核堆栈)。其他情况呢:全局缓冲区,高内存(虽然我现在可以忽略它),可能还有其他类型,我不知道吗?所以我可以重新阐述我的问题:
- 内核中所有内存区域的种类是什么?
- 如何区分它们?
- 如何获取每个区域的页面映射信息?
如果有影响,该代码正在运行于具有MMU的ARM上,并且内核版本至少为2.6.26。
buffer
的目标是否需要满足任何对齐或大小的要求? - Karmastanbuffer &= ~(PAGE_SIZE-1)
来启动upper_layer
。 - Gilles 'SO- stop being evil'