在Fedora 18 内核版本3.8.0下测试虚拟内存实践

在Fedora 18 内核版本3.8.0下测试虚拟内存实践

由于内核文件版本不同,难免有一些问题,只要把头文件关系理清楚就行了,这里不说了,下面直接贴出来测试过可以用的代码吧。

/* mtest_dump_vma_list():打印出当前进程的各个VMA,这个功能我们简称”listvma” mtest_find_vma(): 找出某个虚地址所在的VMA,这个功能我们简称“findvma” my_follow_page( ):根据页表,求出某个虚地址所在的物理页面,这个功能我们简称”findpage” mtest_write_val(), 在某个地址写上具体数据,这个功能我们简称“writeval”. */

#include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/string.h> #include <linux/vmalloc.h> #include <asm/uaccess.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/vmalloc.h>#include <linux/sched.h>#include <linux/highmem.h> MODULE_LICENSE(“GPL”);

/* @如何编写代码查看自己的进程到底有哪些虚拟区?

*/

#define current get_current()struct task_struct;

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); }

/* @如果知道某个虚地址,比如,,0×8049000, 又如何找到这个地址所在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); }

/*

@一个物理页在内核中用struct page来描述。 给定一个虚存区VMA和一个虚地址addr, 找出这个地址所在的物理页面page.

*/

static struct page * my_follow_page(struct vm_area_struct *vma, unsigned long addr) {

pud_t *pud; pmd_t *pmd; pgd_t *pgd; pte_t *pte; spinlock_t *ptl; struct page *page = NULL; struct mm_struct *mm = vma->vm_mm; pgd = pgd_offset(mm, addr); if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) { goto out; } pud = pud_offset(pgd, addr); if (pud_none(*pud) || unlikely(pud_bad(*pud))) goto out; pmd = pmd_offset(pud, addr); if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) { goto out; } pte = pte_offset_map_lock(mm, pmd, addr, &ptl); if (!pte) goto out; if (!pte_present(*pte)) goto unlock; page = pfn_to_page(pte_pfn(*pte)); if (!page) goto unlock; get_page(page); unlock: pte_unmap_unlock(pte, ptl); out: return page; }

/*

@ 根据页表,求出某个虚地址所在的物理页面, 这个功能我们简称”findpage”

*/

static void mtest_find_page(unsigned long addr) {

struct vm_area_struct *vma; struct mm_struct *mm = current->mm; unsigned long kernel_addr; struct page *page; printk(“mtest_write_val\n”); down_read(&mm->mmap_sem); vma = find_vma(mm, addr); page = my_follow_page(vma, addr);

if (!page) { printk(“page not found for 0x%lx\n”, addr); goto out;

} printk(“page found for 0x%lx\n”, addr); kernel_addr = (unsigned long)page_address(page);

kernel_addr += (addr&~PAGE_MASK); printk(“find 0x%lx to kernel address 0x%lx\n”, addr, kernel_addr);

out: up_read(&mm->mmap_sem);

}

/* @你是否有这样的想法, 给某个地址写入自己所想写的数据?

*/

static void mtest_write_val(unsigned long addr, unsigned long val) { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; struct page *page; unsigned long kernel_addr; printk(“mtest_write_val\n”); down_read(&mm->mmap_sem); vma = find_vma(mm, addr); if (vma && addr >= vma->vm_start && (addr + sizeof(val)) < vma->vm_end) { if (!(vma->vm_flags & VM_WRITE)) { printk(“vma is not writable for 0x%lx\n”, addr); goto out; } page = my_follow_page(vma, addr); if (!page) { printk(“page not found for 0x%lx\n”, addr); goto out; }

看不见我将要去的地方,记不得我已经去过的地方。

在Fedora 18 内核版本3.8.0下测试虚拟内存实践

相关文章:

你感兴趣的文章:

标签云: