如何从Linux内核中的任何地址获取结构页 [英] How to get a struct page from any address in the Linux kernel

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

问题描述

我有一个现有的代码,该代码需要一个struct page *列表,并建立一个描述符表以与设备共享内存.该代码的上层当前需要使用vmalloc或用户空间分配的缓冲区,并使用

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获得的缓冲区,内核线程堆栈内的指针或其他我不知道的情况.我唯一的保证是,上层的调用者必须确保相关内存缓冲区在那时映射到内核空间中(即,此时对所有0<=i<size访问buffer[i]是有效的). 如何获取与任意指针相对应的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 测试是否地址来自vmalloc 测试地址是否为有效的虚拟地址(用于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. 如何获取每个页面的映射信息?
  1. What are all the kinds of memory zones in the kernel?
  2. How do I tell them apart?
  3. How do I obtain page mapping information for each of them?

如果有关系,代码将在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内核中的任何地址获取结构页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆