一个程序编译、连接后形成的地址空间就在虚拟地址空间,在内核中,用mm_struct结构描述,为了有效的管理整个虚拟空间,又把此空间分为一个个区间叫做VMA(virtual memory Area),用vma_area_struct结构描述。VMA是虚存管理的基本单位,其组织方式有链表和红黑树。如何编写代码查看自己的进程到底有哪些虚拟区? (以下程序均来自intel OTC的nanhai.zou)
static void mtest_dump_vma_list(void)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
printk("The current process is %s/n",current->comm);
printk("mtest_dump_vma_list/n");
down_read(&mm->mmap_sem);
for (vma = mm->mmap;vma; vma = vma->vm_next) {
printk("VMA 0x%lx-0x%lx ",
vma->vm_start, vma->vm_end);
if (vma->vm_flags & VM_WRITE)
printk("WRITE ");
if (vma->vm_flags & VM_READ)
printk("READ ");
if (vma->vm_flags & VM_EXEC)
printk("EXEC ");
printk("/n");
}
up_read(&mm->mmap_sem);
}
此代码片段比较简单,注意为什么要加down_read()和up_read()?
如果知道某个虚地址,比如,0x8049000, 又如何找到这个地址所在VMA是哪个?
static void mtest_find_vma(unsigned long addr)
{
struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
printk("mtest_find_vma/n");
down_read(&mm->mmap_sem);
vma = find_vma(mm, addr);
if (vma && addr >= vma->vm_start) {
printk("found vma 0x%lx-0x%lx flag %lx for addr 0x%lx/n",
vma->vm_start, vma->vm_end, vma->vm_flags, addr);
} else {
printk("no vma found for %lx/n", addr);
}
up_read(&mm->mmap_sem);
}
内核分配打印出地址信息
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
unsigned long pagemem;
unsigned char *kmallocmem;
unsigned char *vmallocmem;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Li-Jun, WANG Cong");
static int __init init_mmshow(void)
{
pagemem = __get_free_page(GFP_KERNEL);
if(!pagemem)
goto fail3;
printk(KERN_INFO "pagemem=0x%lx/n", pagemem);
kmallocmem = kmalloc(100, GFP_KERNEL);
if(!kmallocmem)
goto fail2;
printk(KERN_INFO "kmallocmem=0x%p/n", kmallocmem);
vmallocmem = vmalloc(1000000);
if(!vmallocmem)
goto fail1;
printk(KERN_INFO "vmallocmem=0x%p/n", vmallocmem);
return 0;
fail1:
kfree(kmallocmem);
fail2:
free_page(pagemem);
fail3:
return -1;
}
static void __exit cleanup_mmshow(void)
{
vfree(vmallocmem);
kfree(kmallocmem);
free_page(pagemem);
}
module_init(init_mmshow);
module_exit(cleanup_mmshow);
运行结果:
The current process is insmod.old
mtest_dump_vma_list
VMA 0x8048000-0x805f000 READ EXEC
VMA 0x805f000-0x8060000 WRITE READ
VMA 0x8060000-0x8078000 WRITE READ EXEC
VMA 0x40000000-0x40015000 READ EXEC
VMA 0x40015000-0x40016000 WRITE READ
VMA 0x40016000-0x40017000 WRITE READ
VMA 0x42000000-0x4212e000 READ EXEC
VMA 0x4212e000-0x42131000 WRITE READ
VMA 0x42131000-0x42133000 WRITE READ
VMA 0xbfff3000-0xc0000000 WRITE READ EXEC
hello world init over
pagemem=0xcda75000
kmallocmem=0xdce51600
vmallocmem=0xe0902000