当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
内存管理实例
发布时间:2011/2/23 10:18:16 来源:城市学习网 编辑:ziteng
  实验内容:在proc 文件系统下,建立一个文件,每次向这个文件写人字符时,调用相应的虚拟内存处理函数
  1./*
  2.mtest_dump_vma_list():打印出当前进程的各个VMA,这个功能我们简称”listvma”
  3.mtest_find_vma(): 找出某个虚地址所在的VMA,这个功能我们简称“findvma”
  4.my_follow_page( ):根据页表,求出某个虚地址所在的物理页面,这个功能我们简称”findpage”
  5.mtest_write_val(), 在某个地址写上具体数据,这个功能我们简称“writeval”。
  6.*/
  7.
  8.#include <linux/module.h>
  9.#include <linux/kernel.h>
  10.#include <linux/proc_fs.h>
  11.#include <linux/string.h>
  12.#include <linux/vmalloc.h>
  13.#include <asm/uaccess.h>
  14.#include <linux/init.h>
  15.#include <linux/slab.h>
  16.#include <linux/mm.h>
  17.#include <linux/vmalloc.h>
  18.MODULE_LICENSE(“GPL”);
  19.
  20./*
  21.@如何编写代码查看自己的进程到底有哪些虚拟区?
  22.
  23.
  24.*/
  25.
  26.static void mtest_dump_vma_list(void)
  27.{
  28.struct mm_struct *mm = current->mm;
  29.struct vm_area_struct *vma;
  30.printk(“The current process is %s\n”,current->comm);
  31.printk(“mtest_dump_vma_list\n”);
  32.down_read(&mm->mmap_sem);
  33.for (vma = mm->mmap;vma; vma = vma->vm_next) {
  34.printk(“VMA 0x%lx-0x%lx ”,
  35.vma->vm_start, vma->vm_end);
  36.if (vma->vm_flags & VM_WRITE)
  37.printk(“WRITE ”);
  38.if (vma->vm_flags & VM_READ)
  39.printk(“READ ”);
  40.if (vma->vm_flags & VM_EXEC)
  41.printk(“EXEC ”);
  42.printk(“\n”);
  43.}
  44.up_read(&mm->mmap_sem);
  45.}
  46.
  47.
  48./*
  49.@如果知道某个虚地址,比如,0×8049000,
  50.又如何找到这个地址所在VMA是哪个?
  51.
  52.
  53.*/
  54.
  55.
  56.static void  mtest_find_vma(unsigned long addr)
  57.{
  58.struct vm_area_struct *vma;
  59.struct mm_struct *mm = current->mm;
  60.
  61.printk(“mtest_find_vma\n”);
  62.
  63.down_read(&mm->mmap_sem);
  64.vma = find_vma(mm, addr);
  65.if (vma && addr >= vma->vm_start) {
  66.printk(“found vma 0x%lx-0x%lx flag %lx for addr 0x%lx\n”,
  67.vma->vm_start, vma->vm_end, vma->vm_flags, addr);
  68.} else {
  69.printk(“no vma found for %lx\n”, addr);
  70.}
  71.up_read(&mm->mmap_sem);
  72.}
  73.
  74./*
  75.
  76.@一个物理页在内核中用struct page来描述。
  77.给定一个虚存区VMA和一个虚地址addr,
  78.找出这个地址所在的物理页面page.
  79.
  80.*/
  81.
  82.
  83.static struct page *
  84.my_follow_page(struct vm_area_struct *vma, unsigned long addr)
  85.{
  86.
  87.pud_t *pud;
  88.pmd_t *pmd;
  89.pgd_t *pgd;
  90.pte_t *pte;
  91.spinlock_t *ptl;
  92.struct page *page = NULL;
  93.struct mm_struct *mm = vma->vm_mm;
  94.pgd = pgd_offset(mm, addr);
  95.if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) {
  96.goto out;
  97.}
  98.pud = pud_offset(pgd, addr);
  99.if (pud_none(*pud) || unlikely(pud_bad(*pud)))
  100.goto out;
  101.pmd = pmd_offset(pud, addr);
  102.if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
  103.goto out;
  104.}
  105.pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
  106.if (!pte)
  107.goto out;
  108.if (!pte_present(*pte))
  109.goto unlock;
  110.page = pfn_to_page(pte_pfn(*pte));
  111.if (!page)
  112.goto unlock;
  113.get_page(page);
  114.unlock:
  115.pte_unmap_unlock(pte, ptl);
  116.out:
  117.return page;
  118.}
  119.
  120.
  121./*
  122.
  123.@ 根据页表,求出某个虚地址所在的物理页面,
  124.这个功能我们简称”findpage”
  125.
  126.
  127.*/
  128.
  129.static void   mtest_find_page(unsigned long addr)
  130.{
  131.
  132.struct vm_area_struct *vma;
  133.struct mm_struct *mm = current->mm;
  134.unsigned long kernel_addr;
  135.struct page *page;
  136.printk(“mtest_write_val\n”);
  137.down_read(&mm->mmap_sem);
  138.vma = find_vma(mm, addr);
  139.page = my_follow_page(vma, addr);
  140.
  141.if (!page)
  142.{
  143.printk(“page not found  for 0x%lx\n”, addr);
  144.goto out;
  145.
  146.}
  147.printk(“page  found  for 0x%lx\n”, addr);
  148.kernel_addr = (unsigned long)page_address(page);
  149.
  150.kernel_addr += (addr&~PAGE_MASK);
  151.printk(“find  0x%lx to kernel address 0x%lx\n”, addr, kernel_addr);
  152.
  153.
  154.
  155.out:
  156.up_read(&mm->mmap_sem);
  157.
  158.}
  159.
  160.
  161.
  162.
  163./* [NextPage]   164.@你是否有这样的想法,
  165.给某个地址写入自己所想写的数据?
  166.
  167.*/
  168.
  169.
  170.
  171.static void
  172.mtest_write_val(unsigned long addr, unsigned long val)
  173.{
  174.struct vm_area_struct *vma;
  175.struct mm_struct *mm = current->mm;
  176.struct page *page;
  177.unsigned long kernel_addr;
  178.printk(“mtest_write_val\n”);
  179.down_read(&mm->mmap_sem);
  180.vma = find_vma(mm, addr);
  181.if (vma && addr >= vma->vm_start && (addr + sizeof(val)) < vma->vm_end) {
  182.if (!(vma->vm_flags & VM_WRITE)) {
  183.printk(“vma is not writable for 0x%lx\n”, addr);
  184.goto out;
  185.}
  186.page = my_follow_page(vma, addr);
  187.if (!page) {
  188.printk(“page not found  for 0x%lx\n”, addr);
  189.goto out;
  190.}
  191.
  192.kernel_addr = (unsigned long)page_address(page);
  193.kernel_addr += (addr&~PAGE_MASK);
  194.printk(“write 0x%lx to address 0x%lx\n”, val, kernel_addr);
  195.*(unsigned long *)kernel_addr = val;
  196.put_page(page);
  197.
  198.} else {
  199.printk(“no vma found for %lx\n”, addr);
  200.}
  201.out:
  202.up_read(&mm->mmap_sem);
  203.}
  204.
  205.
  206.
  207.static ssize_t
  208.mtest_write(struct file *file, const char __user * buffer,
  209.size_t count, loff_t * data)
  210.{
  211.
  212.
  213.printk(“mtest_write  ……  \n”);
  214.char buf[128];
  215.unsigned long val, val2;
  216.if (count > sizeof(buf))
  217.return -EINVAL;
  218.
  219.if (copy_from_user(buf, buffer, count))
  220.return -EINVAL;
  221.
  222.if (memcmp(buf, ”listvma”, 7) == 0)
  223.mtest_dump_vma_list();
  224.
  225.else if (memcmp(buf, ”findvma”, 7) == 0) {
  226.if (sscanf(buf + 7, ”%lx”, &val) == 1) {
  227.mtest_find_vma(val);
  228.}
  229.}
  230.
  231.else if (memcmp(buf, ”findpage”, 8) == 0) {
  232.if (sscanf(buf + 8, ”%lx”, &val) == 1) {
  233.mtest_find_page(val);
  234.
  235.//my_follow_page(vma, addr);
  236.
  237.
  238.}
  239.}
  240.
  241.else  if (memcmp(buf, ”writeval”, 8) == 0) {
  242.if (sscanf(buf + 8, ”%lx %lx”, &val, &val2) == 2) {
  243.mtest_write_val(val, val2);
  244.}
  245.}
  246.return count;
  247.}
  248.
  249.static struct
  250.file_operations proc_mtest_operations = {
  251write        = mtest_write
  252.};
  253.
  254.static struct proc_dir_entry *mtest_proc_entry;
  255.
  256.
  257.//整个操作我们以模块的形式实现,因此,模块的初始化和退出函数如下:
  258.static int __init
  259.mtest_init(void)
  260.{
  261.
  262.mtest_proc_entry = create_proc_entry(“mtest”, 0777, NULL);
  263.if (mtest_proc_entry == NULL) {
  264.printk(“Error creating proc entry\n”);
  265.return -1;
  266.}
  267.printk(“create the filename mtest mtest_init sucess  \n”);
  268.mtest_proc_entry->proc_fops = &proc_mtest_operations;
  269.return 0;
  270.}
  271.
  272.static void
  273.__exit mtest_exit(void)
  274.{
  275.printk(“exit the module……mtest_exit \n”);
  276.remove_proc_entry(“mtest”, NULL);
  277.}
  278.MODULE_LICENSE(“GPL”);
  279.MODULE_DESCRIPTION(“mtest”);
  280.MODULE_AUTHOR(“Zou Nan hai”);
  281.
  282.module_init(mtest_init);
  283.module_exit(mtest_exit);
  下面为Makefile
  1.obj-m := mm.o
  2.
  3.# KDIR is the location of the kernel source.  The current standard is
  4.# to link to the associated source tree from the directory containing
  5.# the compiled modules.
  6.KDIR  := /lib/modules/$(shell uname -r)/build
  7.
  8.# PWD is the current working directory and the location of our module
  9.# source files.
  10.PWD   := $(shell pwd)
  11.
  12.# default is the default make target.  The rule here says to run make
  13.# with a working directory of the directory containing the kernel
  14.# source and compile only the modules in the PWD (local) directory.
  15.default:
  16.$(MAKE) -C $(KDIR) M=$(PWD) modules
  17.clean:
  18.rm -rf *.o *.ko *.mod.c
  下面为测试用例
  [root@HBIDS proc]# echo “listvma” > mtest
  [root@HBIDS proc]# echo “listvma” > mtest
  [root@HBIDS proc]# echo “findvma0xb7f2b001″ > mtest
  [root@HBIDS proc]# echo “findpage0xb7f2b001″ > mtest
  [root@HBIDS proc]# echo “writeval0xb7f2b001 123456″ > mtest
  打印结果为
  The current process is bash
  mtest_dump_vma_list
  VMA 0×8048000-0x80dc000 READ EXEC
  VMA 0x80dc000-0x80e2000 WRITE READ EXEC
  VMA 0x80e2000-0x811e000 WRITE READ EXEC
  VMA 0×42000000-0x4212e000 READ EXEC
  VMA 0x4212e000-0×42131000 WRITE READ EXEC
  VMA 0×42131000-0×42133000 WRITE READ EXEC
  VMA 0xb7d00000-0xb7f00000 READ EXEC
  VMA 0xb7f00000-0xb7f0b000 READ EXEC
  VMA 0xb7f0b000-0xb7f0c000 WRITE READ EXEC
  VMA 0xb7f0c000-0xb7f0d000 WRITE READ EXEC
  VMA 0xb7f0d000-0xb7f0f000 READ EXEC
  VMA 0xb7f0f000-0xb7f10000 WRITE READ EXEC
  VMA 0xb7f10000-0xb7f13000 READ EXEC
  VMA 0xb7f13000-0xb7f14000 WRITE READ EXEC
  VMA 0xb7f2b000-0xb7f31000 READ EXEC
  VMA 0xb7f31000-0xb7f32000 WRITE READ EXEC
  VMA 0xb7f32000-0xb7f47000 READ EXEC
  VMA 0xb7f47000-0xb7f48000 WRITE READ EXEC
  VMA 0xbfd31000-0xbfd47000 WRITE READ EXEC
  mtest_write  ……
  mtest_find_vma
  found vma 0xb7f47000-0xb7f48000 flag 100877 for addr 0xb7f47001
  mtest_write  ……
  mtest_write_val
  page  found  for 0xb7f47001
  find  0xb7f47001 to kernel address 0xc8c4e001
  mtest_write  ……
  mtest_write_val
  write 0×1234 to address 0xc8c4e001
广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved