查找内存区域
该模块实现的功能是:通过向内核模块中传递一个虚存地址,进而查找该地址所在的内存区域。具体查找的功能我们通过find_vma函数来实现,这个函数的原型如下:
struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr);
该函数在指定的地址空间中搜索第一个vm_end大于addr的内存区域。也就是说,当找到了第一个包含该addr或vm_start大于addr的内存区域时,该函数就返回相应区域的vm_area_struct结构体指针,否则返回NULL。那么,find_vma这个函数有可能找到的vma并不是包含addr的内存区域。这是怎么一回事?还是先看图吧。
在图(b)中,所找到的VMA的vm_end大于addr,但是addr却刚好是处于两个VMA之间。因此,find_vma函数所找到的VMA并不包含addr。正因为如此,在find_myvma函数中在使用完find_vma函数后,还要进测addr是否真正包含在vma中。具体函数实现可参考下述代码。本模块完整代码在这里。
static ulong address = 0; static void find_myvma(void) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; printk("find the vma..\n"); down_read(&mm->mmap_sem); vma=find_vma(mm, address); /* when the vma_start > address, it means that the address doesn't belong to the vma */ if(vma && address <= vma->vm_start) { printk("address 0x%lx found in the VMA:0x%lx-0x%lx ",address,vma->vm_start,vma->vm_end); if(vma->vm_flags & VM_READ) printk("r"); else printk("-"); if(vma->vm_flags & VM_WRITE) printk("w"); else printk("-"); if(vma->vm_flags & VM_EXEC) printk("x"); else printk("-"); if(vma->vm_flags & VM_SHARED) printk("s"); else printk("p"); printk("\n"); } else { printk("address 0x%lx didn't find in the VMA which you just now found..\n",address); } up_read(&mm->mmap_sem); } module_param(address, ulong, S_IRUGO);
这个内核模块涉及到了内核模块传递参数的问题。既然我们需要查找某个线性地址addr所在的vma,因此就需要在每次加载内核模块时传入addr这个参数。
请问,为什么给定的虚拟地址不在那个范围呢?
就是说如果给0x2000000,那么它打印出来的
范围没有包括0x2000000啊?是我理解错了吗?
还请指教
[回复一下]
edsionte 回复:
7 8 月, 2014 at 09:18
@凡, 这个只是说明该函数的使用情况。
[回复一下]
凡 回复:
7 8 月, 2014 at 10:30
@edsionte, 不太懂,能否详细点?
我给出的地址也是虚拟地址,打印出来的也是虚拟地址,都是0-3GB的用户空间,那么。。。?
[回复一下]