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结构体
- struct vm_fault {
- unsigned int flags; /* FAULT_FLAG_xxx flags */
- pgoff_t pgoff; /* Logical page offset based on vma */
- void __user *virtual_address; /* Faulting virtual address */
- struct page *page; /* ->fault handlers should return a
- * page here, unless VM_FAULT_NOPAGE
- * is set (which is also implied by
- * VM_FAULT_ERROR).
- */
- };
③为了在2.6.33上编译运行,修改书中代码
书中实例代码
- int mmapnopage_vm_nopage(struct vm_area_struct *vma,
- unsigned long addr,
- int *type)/*修改行*/
- {
- struct page *page;
- unsigned long offset;
- void *page_ptr;
-
- printk("\n");
- printk("CALL NOPAGE %08x\n",addr);
- /*printk("%-25s %08x\n","1)vma->flags",vmf->flags);
- printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
- printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
- printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
- printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
- printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
- printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/
-
- page=NOPAGE_SIGBUS;/*修改行*/
- page_ptr=NULL;
-
- if((NULL==vma)||(NULL==share_memory)){
- printk("return NOPAGE_SIGBUS!\n");
- return NOPAGE_SIGBUS;/*修改行*/
- }
-
- offset=addr-vma->vm_start;/*修改行*/
-
- if(offset>=SHARE_MEM_SIZE){
- printk("return NOPAGE_SIGBUS!\n");
- return NOPAGE_SIGBUS;/*修改行*/
- }
-
- page_ptr=share_memory+offset;
- page=vmalloc_to_page(page_ptr);
- get_page(page);
-
- if(type) *type=VM_FAULT_MINOR;/*修改行*/
-
- return page;/*修改行*/
- }
- struct vm_operations_struct mmapnopage_vm_ops={
- .nopage=mmapnopage_vm_nopage,/*修改行*/
- };
修改后实例代码
- int mmapnopage_vm_fault(struct vm_area_struct *vma,
- struct vm_fault *vmf)/*修改行*/
- {
- struct page *page;
- unsigned long offset;
- void *page_ptr;
-
- printk("\n");
- /*printk("CALL NOPAGE %08x\n",addr);*/
- printk("%-25s %08x\n","1)vma->flags",vmf->flags);
- printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
- printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
- printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
- printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
- printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
- /*printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/
- page_ptr=NULL;
-
- if((NULL==vma)||(NULL==share_memory)){
- printk("return VM_FAULT_SIGBUS!\n");
- return VM_FAULT_SIGBUS;/*修改行*/
- }
-
- offset=vmf->virtual_address-vma->vm_start;/*修改行*/
-
- if(offset>=SHARE_MEM_SIZE){
- printk("return VM_FAULT_SIGBUS!");
- return VM_FAULT_SIGBUS;/*修改行*/
- }
-
- page_ptr=share_memory+offset;
- page=vmalloc_to_page(page_ptr);
- get_page(page);
-
- vmf->page=page;/*修改行*/
-
- return 0;/*修改行*/
- }
- struct vm_operations_struct mmapnopage_vm_ops={
- .fault=mmapnopage_vm_fault,
- };
3、驱动模块源文件mmapnopage_dev.c
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/errno.h>
- #include <linux/fcntl.h>
- #include <linux/vmalloc.h>
- #include <linux/uaccess.h>
- #include <linux/io.h>
- #include <asm/page.h>
- #include <linux/mm.h>
- #define MMAPNOPAGE_DEV_NAME "mmapnopage"
- #define MMAPNOPAGE_DEV_MAJOR 240
- #define SHARE_MEM_PAGE_COUNT 4
- #define SHARE_MEM_SIZE (PAGE_SIZE*SHARE_MEM_PAGE_COUNT)
- char *share_memory=NULL;
- int mmapnopage_vm_fault(struct vm_area_struct *vma,
- struct vm_fault *vmf)
- {
- struct page *page;
- unsigned long offset;
- void *page_ptr;
-
- printk("\n");
- printk("%-25s %08x\n","1)vma->flags",vmf->flags);
- printk("%-25s %08x\n","2)vmf->pgoff",vmf->pgoff);
- printk("%-25s %08x\n","3)vmf->virtual_address",vmf->virtual_address);
- printk("%-25s %08x\n","4)vma->vm_start",vma->vm_start);
- printk("%-25s %08x\n","5)vma->vm_end",vma->vm_end);
- printk("%-25s %08x\n","6)vma->vm_pgoff",vma->vm_pgoff);
- /*printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/
- page_ptr=NULL;
-
- if((NULL==vma)||(NULL==share_memory)){
- printk("return VM_FAULT_SIGBUS!\n");
- return VM_FAULT_SIGBUS;
- }
-
- offset=vmf->virtual_address-vma->vm_start;
-
- if(offset>=SHARE_MEM_SIZE){
- printk("return VM_FAULT_SIGBUS!");
- return VM_FAULT_SIGBUS;
- }
-
- page_ptr=share_memory+offset;
- page=vmalloc_to_page(page_ptr);
- get_page(page);
-
- vmf->page=page;
-
- return 0;
- }
- struct vm_operations_struct mmapnopage_vm_ops={
- .fault=mmapnopage_vm_fault,
- };
- int mmapnopage_mmap(struct file *filp,struct vm_area_struct *vma)
- {
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops=&mmapnopage_vm_ops;
- return 0;
- }
- struct file_operations mmapnopage_fops={
- .owner=THIS_MODULE,
- .mmap=mmapnopage_mmap,
- };
- int mmapnopage_init(void)
- {
- int lp;
- int result;
-
- result=register_chrdev(MMAPNOPAGE_DEV_MAJOR,
- MMAPNOPAGE_DEV_NAME,
- &mmapnopage_fops);
- if(result<0){
- return result;
- }
-
- share_memory=vmalloc(SHARE_MEM_SIZE);
- for(lp=0;lp<SHARE_MEM_PAGE_COUNT;lp++){
- sprintf(share_memory+PAGE_SIZE*lp,"TEST %d",lp);
- }
- return 0;
- }
- void mmapnopage_exit(void)
- {
- if(share_memory!=NULL){
- vfree(share_memory);
- }
- unregister_chrdev(MMAPNOPAGE_DEV_MAJOR,
- MMAPNOPAGE_DEV_NAME);
- }
- module_init(mmapnopage_init);
- module_exit(mmapnopage_exit);
- MODULE_LICENSE("Dual BSD/GPL");
4、Makefile
- obj-m += mmapnopage_dev.o
- CURRENT_PATH := $(shell pwd)
- LINUX_KERNEL := $(shell uname -r)
- LINUX_KERNEL_PATH := /usr/src/linux-$(LINUX_KERNEL)
- all:
- make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
- clean:
- #make -C $(LINUX_KERNEL_PAHT) M=$(CURRENT_PATH) clean
- rm *.mod.*
- rm *.order
- rm *.o
- rm *.symvers
5、应用程序源文件mmapnopage_app.c
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #define DEVICE_FILENAME "/dev/mmapnopage"
- #define SHARE_MEM_PAGE_COUNT 5
- #define SHARE_MEM_SIZE (4096*SHARE_MEM_PAGE_COUNT)
- int main()
- {
- int dev;
- int loop;
- char *ptrdata;
-
- dev=open(DEVICE_FILENAME,O_RDWR|O_NDELAY);
-
- if(dev>=0){
- printf("open file success!\n");
- ptrdata=(char*)mmap(0,
- SHARE_MEM_SIZE,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- dev,
- 0);
- for(loop=0;loop<SHARE_MEM_PAGE_COUNT;loop++){
- printf("[%-10s%x]\n",ptrdata+4096*loop,ptrdata+4096*loop);
- }
- munmap(ptrdata,SHARE_MEM_SIZE);
- close(dev);
- }
- return 0;
- }
6、实施方法及运行结果
- ~/nopage_mmap# mknod /dev/mmapnopage c 240 0
- ~/nopage_mmap# make
- ~/nopage_mmap# gcc mmapnopage_app.c -o mmapnopage_app
- ~/nopage_mmap# insmod mmapnopage_dev.ko
- ~/nopage_mmap# ./mmapnopage_app
- open file
- [TEST 0 b77c1000]
- [TEST 1 b77c2000]
- [TEST 2 b77c3000]
- [TEST 3 b77c4000]
- ~/nopage_mmap# dmesg
- [ 385.633677]
- [ 385.633946] 1)vma->flags 00000000
- [ 385.633965] 2)vmf->pgoff 00000000
- [ 385.633978] 3)vmf->virtual_address b77c1000
- [ 385.633989] 4)vma->vm_start b77c1000
- [ 385.634001] 5)vma->vm_end b77c5000
- [ 385.634013] 6)vma->vm_pgoff 00000000
- [ 385.634146]
- [ 385.634149] 1)vma->flags 00000000
- [ 385.634152] 2)vmf->pgoff 00000001
- [ 385.634154] 3)vmf->virtual_address b77c2000
- [ 385.634156] 4)vma->vm_start b77c1000
- [ 385.634158] 5)vma->vm_end b77c5000
- [ 385.634160] 6)vma->vm_pgoff 00000000
- [ 385.634174]
- [ 385.634177] 1)vma->flags 00000000
- [ 385.634180] 2)vmf->pgoff 00000002
- [ 385.634182] 3)vmf->virtual_address b77c3000
- [ 385.634184] 4)vma->vm_start b77c1000
- [ 385.634186] 5)vma->vm_end b77c5000
- [ 385.634188] 6)vma->vm_pgoff 00000000
- [ 385.634202]
- [ 385.634204] 1)vma->flags 00000000
- [ 385.634207] 2)vmf->pgoff 00000003
- [ 385.634209] 3)vmf->virtual_address b77c4000
- [ 385.634211] 4)vma->vm_start b77c1000
- [ 385.634213] 5)vma->vm_end b77c5000
- [ 385.634215] 6)vma->vm_pgoff 00000000
7、移除模块及设备文件
- ~/nopage_mmap# rm /dev/mmapnopage
- ~/nopage_mmap# rmmod mmapnopage_dev
阅读(809) | 评论(0) | 转发(0) |