Linux设备驱动remap_pfn_range() 和remap_page_range()

来源:互联网 发布:锁定mac地址 编辑:程序博客网 时间:2024/06/05 20:17

转载:http://blog.csdn.net/dijkstar/article/details/51347408

LDD3的开发环境推荐的是2.6.10,安装了RHEL4-update4,其内核版本为2.6.9.42,编译mmap的程序时报错:Unknown symbol remap_pfn_range

在网上查了下,应将上述报错的函数改为remap_page_range,并且remap_page_range不再推荐使用了,两个内核函数第二个参数定义不相同:

[cpp] view plain copy
  1. int remap_page_range(struct vm_area_struct *vma,  
  2.             unsigned long from,   
  3.             unsigned long phys_addr, //  
  4.             unsigned long size,   
  5.             pgprot_t prot)  
  6.               
  7.   
  8. int remap_pfn_range(struct vm_area_struct *vma,  
  9.             unsigned long addr,  
  10.             unsigned long pfn,      //注意和上述的不同  
  11.             unsigned long size,  
  12.             pgprot_t prot)    

直接看下面的一段程序,在注释中已经将两个函数的使用区分出来了。使用前,先mknod /dev/mymap c 60 0

[cpp] view plain copy
  1. #include <linux/delay.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/module.h>  
  4. #include <linux/init.h>  
  5. #include <linux/mm.h>  
  6. #include <linux/fs.h>  
  7. #include <linux/types.h>  
  8. #include <linux/delay.h>  
  9. #include <linux/moduleparam.h>  
  10. #include <linux/slab.h>  
  11. #include <linux/errno.h>  
  12. #include <linux/ioctl.h>  
  13. #include <linux/cdev.h>  
  14. #include <linux/string.h>  
  15. #include <linux/list.h>  
  16. #include <linux/pci.h>  
  17. //#include <linux/gpio.h>  
  18.   
  19.   
  20. #define DEVICE_NAME "mymap"  
  21.   
  22.   
  23. static unsigned char array[10]={0,1,2,3,4,5,6,7,8,9};  
  24. static unsigned char *buffer;  
  25.   
  26.   
  27. static int my_open(struct inode *inode, struct file *file)  
  28. {  
  29.     return 0;  
  30. }  
  31.   
  32.   
  33. static int my_map(struct file *filp, struct vm_area_struct *vma)  
  34. {      
  35.     unsigned long page;  
  36.     unsigned char i;  
  37.     unsigned long start = (unsigned long)vma->vm_start;  
  38.     //unsigned long end =  (unsigned long)vma->vm_end;  
  39.     unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);  
  40.   
  41.     //得到物理地址  
  42.     page = virt_to_phys(buffer);      
  43.     //将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上  
  44.     //if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,PAGE_SHARED))//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到  
  45.     if(remap_page_range(vma,start,page,size,PAGE_SHARED))//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到      
  46.         return -1;  
  47.   
  48.     //往该内存写10字节数据  
  49.     for(i=0;i<10;i++)  
  50.         buffer[i] = array[i];  
  51.       
  52.     return 0;  
  53. }  
  54.   
  55.   
  56. static struct file_operations dev_fops = {  
  57.     .owner    = THIS_MODULE,  
  58.     .open    = my_open,  
  59.     .mmap   = my_map,  
  60. };  
  61.   
  62. /* 
  63. static struct miscdevice misc = { 
  64.     .minor = MISC_DYNAMIC_MINOR, 
  65.     .name = DEVICE_NAME, 
  66.     .fops = &dev_fops, 
  67. }; 
  68. */  
  69.   
  70. static int __init dev_init(void)  
  71. {  
  72.     int ret;      
  73.   
  74.     //注册混杂设备  
  75.     //ret = misc_register(&misc);  
  76.       
  77.       
  78.     ret = register_chrdev(60, DEVICE_NAME, &dev_fops);  
  79.     if (ret < 0)   
  80.     {  
  81.             printk("<1> memory: can't obtain major number %d\n", 60);  
  82.             return ret;  
  83.     }  
  84.   
  85.       
  86.     //内存分配  
  87.     buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);  
  88.     //将该段内存设置为保留  
  89.     SetPageReserved(virt_to_page(buffer));  
  90.   
  91.     return ret;  
  92. }  
  93.   
  94.   
  95. static void __exit dev_exit(void)  
  96. {  
  97.     //注销设备  
  98.     //misc_deregister(&misc);  
  99.      unregister_chrdev(60, DEVICE_NAME);  
  100.        
  101.        
  102.     //清除保留  
  103.     ClearPageReserved(virt_to_page(buffer));  
  104.     //释放内存  
  105.     kfree(buffer);  
  106. }  
  107.   
  108.   
  109. module_init(dev_init);  
  110. module_exit(dev_exit);  
  111. MODULE_LICENSE("Dual BSD/GPL");  

应用程序:

[cpp] view plain copy
  1. #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #include <fcntl.h>  
  6. #include <linux/fb.h>  
  7. #include <sys/mman.h>  
  8. #include <sys/ioctl.h>   
  9.   
  10. #define PAGE_SIZE 4096  
  11.   
  12.   
  13. int main(int argc , char *argv[])  
  14. {  
  15.     int fd;  
  16.     int i;  
  17.     unsigned char *p_map;  
  18.       
  19.     //打开设备  
  20.     fd = open("/dev/mymap",O_RDWR);  
  21.     if(fd < 0)  
  22.     {  
  23.         printf("open fail\n");  
  24.         exit(1);  
  25.     }  
  26.   
  27.     //内存映射  
  28.     p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);  
  29.     if(p_map == MAP_FAILED)  
  30.     {  
  31.         printf("mmap fail\n");  
  32.         goto here;  
  33.     }  
  34.   
  35.     //打印映射后的内存中的前10个字节内容  
  36.     for(i=0;i<10;i++)  
  37.         printf("%d\n",p_map[i]);  
  38.       
  39.   
  40. here:  
  41.     munmap(p_map, PAGE_SIZE);  
  42.     return 0;  
  43. }  

makefile文件:

[plain] view plain copy
  1. obj-m := testdrv.o  
  2. PWD       := $(shell pwd)  
  3. all:  
  4.     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules  
  5. clean:  
  6.     rm -rf *.o *~ core .*.cmd *.mod.c ./tmp_version 
原创粉丝点击