linux_dev_学习笔记_内存映射nopage()

2012年3月25日  Sunday
 
1、内核版本号2.6.33.20
 
2、nopage()实例
 
1)与上篇中remap_pfn_range()一样在书中的实例的实现也有所不同
 
2) struct vm_operations_struct
①在2.6.23之前struct vm_operations_struct中只有
struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type)
从2.6.24后在struct vm_operations_struct中的出现
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf)
并在一段时间里,内核同时支持这两个函数,但后面的内核版本取消了
struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type)
在内核2.6.33.20中就取消了该函数
 
②int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf)中struct vm_fault结构体

  1. struct vm_fault {
  2.         unsigned int flags; /* FAULT_FLAG_xxx flags */
  3.         pgoff_t pgoff; /* Logical page offset based on vma */
  4.         void __user *virtual_address; /* Faulting virtual address */

  5.         struct page *page; /* ->fault handlers should return a
  6.                                          * page here, unless VM_FAULT_NOPAGE
  7.                                          * is set (which is also implied by
  8.                                          * VM_FAULT_ERROR).
  9.                                          */
  10. };

③为了在2.6.33上编译运行,修改书中代码
 
书中实例代码

点击(此处)折叠或打开

  1. int mmapnopage_vm_nopage(struct vm_area_struct *vma,
  2.             unsigned long addr,
  3.             int *type)/*修改行*/
  4. {
  5.     struct page *page;
  6.     unsigned long offset;
  7.     void *page_ptr;
  8.     
  9.     printk("\n");
  10.     printk("CALL NOPAGE %08x\n",addr);
  11.     /*printk("%-25s %08x\n","1)vma->flags",vmf->flags);
  12.     printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
  13.     printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
  14.     printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
  15.     printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
  16.     printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
  17.     printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/
  18.     
  19.     page=NOPAGE_SIGBUS;/*修改行*/
  20.     page_ptr=NULL;
  21.     
  22.     if((NULL==vma)||(NULL==share_memory)){
  23.         printk("return NOPAGE_SIGBUS!\n");
  24.         return NOPAGE_SIGBUS;/*修改行*/
  25.     }
  26.     
  27.     offset=addr-vma->vm_start;/*修改行*/
  28.     
  29.     if(offset>=SHARE_MEM_SIZE){
  30.         printk("return NOPAGE_SIGBUS!\n");
  31.         return NOPAGE_SIGBUS;/*修改行*/
  32.     }
  33.     
  34.     page_ptr=share_memory+offset;
  35.     page=vmalloc_to_page(page_ptr);
  36.     get_page(page);
  37.     
  38.     if(type) *type=VM_FAULT_MINOR;/*修改行*/
  39.     
  40.     return page;/*修改行*/
  41. }

  42. struct vm_operations_struct mmapnopage_vm_ops={
  43.     .nopage=mmapnopage_vm_nopage,/*修改行*/
  44. };

修改后实例代码

点击(此处)折叠或打开

  1. int mmapnopage_vm_fault(struct vm_area_struct *vma,
  2.             struct vm_fault *vmf)/*修改行*/
  3. {
  4.     struct page *page;
  5.     unsigned long offset;
  6.     void *page_ptr;
  7.     
  8.     printk("\n");
  9.     /*printk("CALL NOPAGE %08x\n",addr);*/
  10.     printk("%-25s %08x\n","1)vma->flags",vmf->flags);
  11.     printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
  12.     printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
  13.     printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
  14.     printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
  15.     printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
  16.     /*printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/

  17.     page_ptr=NULL;
  18.     
  19.     if((NULL==vma)||(NULL==share_memory)){
  20.         printk("return VM_FAULT_SIGBUS!\n");
  21.         return VM_FAULT_SIGBUS;/*修改行*/
  22.     }
  23.     
  24.     offset=vmf->virtual_address-vma->vm_start;/*修改行*/
  25.     
  26.     if(offset>=SHARE_MEM_SIZE){
  27.         printk("return VM_FAULT_SIGBUS!");
  28.         return VM_FAULT_SIGBUS;/*修改行*/
  29.     }
  30.     
  31.     page_ptr=share_memory+offset;
  32.     page=vmalloc_to_page(page_ptr);
  33.     get_page(page);
  34.     
  35.     vmf->page=page;/*修改行*/
  36.     
  37.     return 0;/*修改行*/
  38. }

  39. struct vm_operations_struct mmapnopage_vm_ops={
  40.     .fault=mmapnopage_vm_fault,
  41. };

3、驱动模块源文件mmapnopage_dev.c

点击(此处)折叠或打开

  1. #include <linux/init.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>

  4. #include <linux/fs.h>
  5. #include <linux/types.h>
  6. #include <linux/errno.h>
  7. #include <linux/fcntl.h>

  8. #include <linux/vmalloc.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/io.h>

  11. #include <asm/page.h>
  12. #include <linux/mm.h>

  13. #define MMAPNOPAGE_DEV_NAME "mmapnopage"
  14. #define MMAPNOPAGE_DEV_MAJOR 240

  15. #define SHARE_MEM_PAGE_COUNT 4
  16. #define SHARE_MEM_SIZE (PAGE_SIZE*SHARE_MEM_PAGE_COUNT)

  17. char *share_memory=NULL;



  18. int mmapnopage_vm_fault(struct vm_area_struct *vma,
  19.             struct vm_fault *vmf)
  20. {
  21.     struct page *page;
  22.     unsigned long offset;
  23.     void *page_ptr;
  24.     
  25.     printk("\n");
  26.     printk("%-25s %08x\n","1)vma->flags",vmf->flags);
  27.     printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
  28.     printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
  29.     printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
  30.     printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
  31.     printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
  32.     /*printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/

  33.     page_ptr=NULL;
  34.     
  35.     if((NULL==vma)||(NULL==share_memory)){
  36.         printk("return VM_FAULT_SIGBUS!\n");
  37.         return VM_FAULT_SIGBUS;
  38.     }
  39.     
  40.     offset=vmf->virtual_address-vma->vm_start;
  41.     
  42.     if(offset>=SHARE_MEM_SIZE){
  43.         printk("return VM_FAULT_SIGBUS!");
  44.         return VM_FAULT_SIGBUS;
  45.     }
  46.     
  47.     page_ptr=share_memory+offset;
  48.     page=vmalloc_to_page(page_ptr);
  49.     get_page(page);
  50.     
  51.     vmf->page=page;
  52.     
  53.     return 0;
  54. }

  55. struct vm_operations_struct mmapnopage_vm_ops={
  56.     .fault=mmapnopage_vm_fault,
  57. };

  58. int mmapnopage_mmap(struct file *filp,struct vm_area_struct *vma)
  59. {
  60.     vma->vm_flags |= VM_RESERVED;
  61.     vma->vm_ops=&mmapnopage_vm_ops;
  62.     return 0;
  63. }

  64. struct file_operations mmapnopage_fops={
  65.     .owner=THIS_MODULE,
  66.     .mmap=mmapnopage_mmap,
  67. };

  68. int mmapnopage_init(void)
  69. {
  70.     int lp;
  71.     int result;
  72.     
  73.     result=register_chrdev(MMAPNOPAGE_DEV_MAJOR,
  74.                 MMAPNOPAGE_DEV_NAME,
  75.                 &mmapnopage_fops);
  76.     if(result<0){
  77.         return result;
  78.     }
  79.     
  80.     share_memory=vmalloc(SHARE_MEM_SIZE);
  81.     for(lp=0;lp<SHARE_MEM_PAGE_COUNT;lp++){
  82.         sprintf(share_memory+PAGE_SIZE*lp,"TEST %d",lp);
  83.     }
  84.     return 0;
  85. }

  86. void mmapnopage_exit(void)
  87. {
  88.     if(share_memory!=NULL){
  89.         vfree(share_memory);
  90.     }
  91.     unregister_chrdev(MMAPNOPAGE_DEV_MAJOR,
  92.             MMAPNOPAGE_DEV_NAME);
  93. }

  94. module_init(mmapnopage_init);
  95. module_exit(mmapnopage_exit);

  96. MODULE_LICENSE("Dual BSD/GPL");

4、Makefile

点击(此处)折叠或打开

  1. obj-m += mmapnopage_dev.o

  2. CURRENT_PATH := $(shell pwd)

  3. LINUX_KERNEL := $(shell uname -r)

  4. LINUX_KERNEL_PATH := /usr/src/linux-$(LINUX_KERNEL)

  5. all:
  6.     make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
  7. clean:
  8.     #make -C $(LINUX_KERNEL_PAHT) M=$(CURRENT_PATH) clean
  9.     rm *.mod.*
  10.     rm *.order
  11.     rm *.o
  12.     rm *.symvers

5、应用程序源文件mmapnopage_app.c

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <sys/ioctl.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <sys/mman.h>

  8. #define DEVICE_FILENAME "/dev/mmapnopage"
  9. #define SHARE_MEM_PAGE_COUNT 5
  10. #define SHARE_MEM_SIZE (4096*SHARE_MEM_PAGE_COUNT)

  11. int main()
  12. {
  13.     int dev;
  14.     int loop;
  15.     char *ptrdata;
  16.     
  17.     dev=open(DEVICE_FILENAME,O_RDWR|O_NDELAY);
  18.     
  19.     if(dev>=0){
  20.         printf("open file success!\n");
  21.         ptrdata=(char*)mmap(0,
  22.                 SHARE_MEM_SIZE,
  23.                 PROT_READ|PROT_WRITE,
  24.                 MAP_SHARED,
  25.                 dev,
  26.                 0);
  27.         for(loop=0;loop<SHARE_MEM_PAGE_COUNT;loop++){
  28.             printf("[%-10s%x]\n",ptrdata+4096*loop,ptrdata+4096*loop);
  29.         }
  30.         munmap(ptrdata,SHARE_MEM_SIZE);
  31.         close(dev);
  32.     }
  33.     return 0;
  34. }

6、实施方法及运行结果

点击(此处)折叠或打开

  1. ~/nopage_mmap# mknod /dev/mmapnopage c 240 0
  2. ~/nopage_mmap# make
  3. ~/nopage_mmap# gcc mmapnopage_app.c -o mmapnopage_app
  4. ~/nopage_mmap# insmod mmapnopage_dev.ko
  5. ~/nopage_mmap# ./mmapnopage_app
  6. open file
  7. [TEST 0 b77c1000]
  8. [TEST 1 b77c2000]
  9. [TEST 2 b77c3000]
  10. [TEST 3 b77c4000]
  11. ~/nopage_mmap# dmesg
  12. [ 385.633677]
  13. [ 385.633946] 1)vma->flags 00000000
  14. [ 385.633965] 2)vmf->pgoff 00000000
  15. [ 385.633978] 3)vmf->virtual_address b77c1000
  16. [ 385.633989] 4)vma->vm_start b77c1000
  17. [ 385.634001] 5)vma->vm_end b77c5000
  18. [ 385.634013] 6)vma->vm_pgoff 00000000
  19. [ 385.634146]
  20. [ 385.634149] 1)vma->flags 00000000
  21. [ 385.634152] 2)vmf->pgoff 00000001
  22. [ 385.634154] 3)vmf->virtual_address b77c2000
  23. [ 385.634156] 4)vma->vm_start b77c1000
  24. [ 385.634158] 5)vma->vm_end b77c5000
  25. [ 385.634160] 6)vma->vm_pgoff 00000000
  26. [ 385.634174]
  27. [ 385.634177] 1)vma->flags 00000000
  28. [ 385.634180] 2)vmf->pgoff 00000002
  29. [ 385.634182] 3)vmf->virtual_address b77c3000
  30. [ 385.634184] 4)vma->vm_start b77c1000
  31. [ 385.634186] 5)vma->vm_end b77c5000
  32. [ 385.634188] 6)vma->vm_pgoff 00000000
  33. [ 385.634202]
  34. [ 385.634204] 1)vma->flags 00000000
  35. [ 385.634207] 2)vmf->pgoff 00000003
  36. [ 385.634209] 3)vmf->virtual_address b77c4000
  37. [ 385.634211] 4)vma->vm_start b77c1000
  38. [ 385.634213] 5)vma->vm_end b77c5000
  39. [ 385.634215] 6)vma->vm_pgoff 00000000

7、移除模块及设备文件

  1. ~/nopage_mmap# rm /dev/mmapnopage
  2. ~/nopage_mmap# rmmod mmapnopage_dev
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值