查找内存区域
该模块实现的功能是:通过向内核模块中传递一个虚存地址,进而查找该地址所在的内存区域。具体查找的功能我们通过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的用户空间,那么。。。?
[回复一下]