本文介绍了如何从 Linux 内核中的任何地址获取结构页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有现有代码,它采用 struct page * 列表并构建描述符表以与设备共享内存.该代码的上层目前期望使用 vmalloc 或用户空间分配缓冲区,并使用 vmalloc_to_page 获取对应的struct page *.

I have existing code that takes a list of struct page * and builds a descriptor table to share memory with a device. The upper layer of that code currently expects a buffer allocated with vmalloc or from user space, and uses vmalloc_to_page to obtain the corresponding struct page *.

现在上层需要处理各种内存,而不仅仅是通过vmalloc获得的内存.这可能是使用 kmalloc 获得的缓冲区、内核线程堆栈内的指针或其他我不知道的情况.我唯一的保证是这个上层的调用者必须确保有问题的内存缓冲区在那一点被映射到内核空间中(即访问 buffer[i] 对于所有 buffer[i] 是有效的)code>0 此时).如何获取任意指针对应的struct page*?

Now the upper layer needs to cope with all kinds of memory, not just memory obtained through vmalloc. This could be a buffer obtained with kmalloc, a pointer inside the stack of a kernel thread, or other cases that I'm not aware of. The only guarantee I have is that the caller of this upper layer must ensure that the memory buffer in question is mapped in kernel space at that point (i.e. it is valid to access buffer[i] for all 0<=i<size at this point). How do I obtain a struct page* corresponding to an arbitrary pointer?

把它放在伪代码中,我有这个:

Putting it in pseudo-code, I have this:

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).

and I now need to change upper_layer to cope with any valid buffer (without changing lower_layer).

我找到了 virt_to_page,其中 Linux 设备驱动程序 表示对逻辑地址,[不是]来自 vmalloc 的内存或高端内存"的操作.此外,is_vmalloc_addr 测试地址是否来自 vmallocvirt_addr_valid 测试地址是否是有效的虚拟地址(virt_to_page 的素材;这包括 kmalloc(GFP_KERNEL) 和内核堆栈).其他情况如何:全局缓冲区、高内存(总有一天会到来,但我现在可以忽略它),可能还有我不知道的其他类型?所以我可以将我的问题重新表述为:

I've found virt_to_page, which Linux Device Drivers indicates operates on "a logical address, [not] memory from vmalloc or high memory". Furthermore, is_vmalloc_addr tests whether an address comes from vmalloc, and virt_addr_valid tests if an address is a valid virtual address (fodder for virt_to_page; this includes kmalloc(GFP_KERNEL) and kernel stacks). What about other cases: global buffers, high memory (it'll come one day, though I can ignore it for now), possibly other kinds that I'm not aware of? So I could reformulate my question as:

  1. 内核中有哪些所有内存区域?
  2. 我如何区分它们?
  3. 如何获取每个页面的映射信息?

如果有关系,代码在 ARM(带有 MMU)上运行,内核版本至少为 2.6.26.

If it matters, the code is running on ARM (with an MMU), and the kernel version is at least 2.6.26.

推荐答案

我猜你想要的是页表遍历,比如(警告,不是实际代码,锁定丢失等):

I guess what you want is a page table walk, something like (warning, not actual code, locking missing etc):

struct mm_struct *mm = current->mm;
pgd = pgd_offset(mm, address);
pmd = pmd_offset(pgd, address);
pte = *pte_offset_map(pmd, address);
page = pte_page(pte);

但是你应该非常小心.例如,您获得的 kmalloc 地址很可能不是页面对齐的.这对我来说听起来像是一个非常危险的 API.

But you you should be very very careful with this. the kmalloc address you got might very well be not page aligned for example. This sounds like a very dangerous API to me.

这篇关于如何从 Linux 内核中的任何地址获取结构页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-04 13:38