linux设备驱动开发学习之旅--使用文件私有数据的字符设备驱动

来源:互联网 发布:金晨人品知乎 编辑:程序博客网 时间:2024/05/21 14:00
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * Author:hasen 
  3.  * 参考 :《linux设备驱动开发详解》 
  4.  * 简介:android小菜鸟的linux 
  5.  *           设备驱动开发学习之旅 
  6.  * 主题:使用文件私有数据的字符设备驱动 
  7.  * Date:2014-10-31  
  8.  */  
  9.   
  10. #include <linux/module.h>  
  11. #include <linux/types.h>  
  12. #include <linux/fs.h>  
  13. #include <linux/error.h>  
  14. #include <linux/mm.h>  
  15. #include <linux/sched.h>  
  16. #include <linux/cdev.h>  
  17. #include <linux/init.h>  
  18. #include <asm/io.h>  
  19. #include <asm/system.h>  
  20. #include <asm/uaccess.h>  
  21.   
  22. #define GLOBALMEM_SIZE 0x1000 /*全局变量大小:4KB*/  
  23. #define MEM_CLEAR 0x1 /*清零全局内存*/  
  24. #define GLOBALMEM_MAJOR 250 /*预设的globalmem的主设备号*/  
  25.   
  26. static int globalmem_major =GLOBALMEM_MAJOR ;  
  27. /*globalmem设备结构体*/  
  28. struct globalmem_dev {  
  29.     struct cdev cdev ; /*cdev结构体*/  
  30.     unsigned char mem[GLOBALMEM_SIZE] ; /*全局内存*/  
  31. } ;  
  32.   
  33. struct globalmem_dev *globalmem_devp ;/*设备结构体实例*/  
  34.   
  35. /*globalmem设备文件打开函数*/  
  36. int globalmem_open(struct inode *inode ,struct file *filp)  
  37. {  
  38.     /*将设备结构体指针赋值给文件私有数据指针*/  
  39.     filp->private_data = globalmem_devp ;  
  40.     return 0 ;  
  41. }  
  42.   
  43. /*globalmem驱动设备文件释放函数*/  
  44. int globalmem_release(struct inode *inode,struct file *filp)  
  45. {  
  46.     return 0 ;  
  47. }  
  48.   
  49. /*globalmem设备驱动模块加载函数*/  
  50. int globalmem_init(void)  
  51. {  
  52.     int result ;  
  53.     dev_t devno = MKDEV(globalmem_major ,0) ;  
  54.       
  55.     /*申请字符设备驱动区域*/  
  56.     if(globalmem_major)  
  57.         result = register_chrdev_region(devno,1,"globalmem") ;  
  58.     else{  
  59.         /*动态获得主设备号*/  
  60.         result = alloc_chrdev_region(&devno,0,1,"globalmem") ;  
  61.         globalmem_major = MAJOR(devno) ;  
  62.     }  
  63.     if(result < 0)  
  64.         return result ;  
  65.     /*动态申请设备结构体的内存*/  
  66.     globalmem_devp = kmalloc(sizeof(struct globalmem_dev),GFP_KERNEL) ;  
  67.     if(!globalmem_devp){ /*申请失败*/  
  68.         result = -ENOMEM ;  
  69.         goto fail_malloc ;  
  70.     }  
  71.       
  72.     memset(globalmem_devp,0,sizeof(struct globalmem_dev)) ;  
  73.       
  74.     globalmem_setup_cdev(&globalmem_devp,0) ;  
  75.     return 0 ;  
  76. fail_malloc :  
  77.     unregister_chrdev_region(devno,1) ;  
  78.     return result ;  
  79. }  
  80.   
  81. /*globalmem设备驱动模块卸载函数*/  
  82. void globalmem_exit(void)  
  83. {  
  84.     cdev_del(&globalmem_devp->cdev) ;/*删除cdev结构*/  
  85.     kfree(globalmem_devp) ;  
  86.     unregister_chrdev_region(MKDEV(globalmem_major,0),1) ;/*注销设备区域*/  
  87. }  
  88.   
  89. /*初始化并添加cdev结构体*/  
  90. static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)  
  91. {  
  92.     int err , devno = MKDEV(globalmem_major ,index) ;  
  93.     cdev_init(&dev->cdev,&globalmem_fops) ;  
  94.     dev->cdev.owner = THIS_MODULE ;  
  95.     err = cdev_add(&dev->cdev,devno,1) ;  
  96.     if(err)  
  97.         printk(KERN_NOTICE "Error %d adding globalmem %d\n",err,index) ;  
  98. }  
  99.   
  100. /*globalmem设备驱动文件操作结构体*/  
  101. const struct file_operations globalmem_fops = {  
  102.     .owner = THIS_MODULE ,  
  103.     .llseek = globalmem_llseek ,  
  104.     .read = globalmem_read ,  
  105.     .write = globalmem_write ,  
  106.     .ioctl = globalmem_ioctl ,  
  107.     .open = globalmem_open ,  
  108.     .release = globalmem_release ,  
  109. } ;  
  110.   
  111. /*globalmem设备驱动读函数*/  
  112. static ssize_t globalmem_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos )  
  113. {  
  114.     unsigned long p = *ppos ;  
  115.     int ret = 0 ;  
  116.     struct globalmem_dev *dev = filp->private_data ;/*获取设备结构体指针*/  
  117.       
  118.     /*分析和获取有效的读长度*/  
  119.     if(p >= GLOBALMEM_SIZE)/*要读的偏移位置越界*/  
  120.         return 0 ;  
  121.     if(count > GLOBALMEM_SIZE - p)/*要读的字节数太大*/  
  122.         count = GLOBALMEM_SIZE -P ;  
  123.       
  124.     /*内核空间 -> 用户空间*/  
  125.     if(copy_to_user(buf,(void *)(dev->mem + p),count))  
  126.         ret = -EFAULT ;  
  127.     else{  
  128.         *ppos += count ;  
  129.         ret = count ;  
  130.         printk(KERN_INFO "read %d bytes from %d\n",count,p) ;     
  131.     }  
  132. }  
  133.   
  134. /*globalmem设备驱动写函数*/  
  135. static ssize_t globalmem_write(struct file *filp,const char __user buf,size_t count,loff_t *ppos)  
  136. {  
  137.     unsigned long p = *ppos ;   
  138.     int ret = 0 ;  
  139.     struct globalmem_dev *dev = filp->private_data ;/*获取设备结构体指针*/  
  140.       
  141.     /*分析和获取有效的写长度*/  
  142.     if(p >= GLOBALMEM_SIZE) /*要写的偏移位置越界*/  
  143.         return 0 ;  
  144.     if(count > GLOBALMEM_SIZE - p ) /*要写的字节数太大*/  
  145.         count = GLOBALMEM_SIZE - p ;  
  146.       
  147.     /*用户空间 -> 内核空间*/  
  148.     if(copy_from_user(dev->mem+p, buf,count))  
  149.         ret = -EFAULT ;  
  150.     else{  
  151.         *ppos += count ;  
  152.         ret = count ;  
  153.         printk(KERN_INFO "write %d bytes from %d\n",count,p) ;  
  154.     }  
  155.     return ret ;  
  156. }  
  157.   
  158. /*globalmem设备驱动seek()函数*/  
  159. static loff_t globalmem_llseek(struct file *filp,loff_t offset,int orig)  
  160. {  
  161.     loff_t ret ;  
  162.     switch(orig){  
  163.     case 0: /*从文件开头开始偏移*/  
  164.         if(offset <0){  
  165.             ret = -EINVAL ;  
  166.             break ;  
  167.         }  
  168.         if((unsigned int)offset >GLOBALMEM_SIZE){  
  169.             ret = -EINVAL ;  
  170.             break ;  
  171.         }  
  172.         flip->f_pos += offset ;  
  173.         ret = flip->f_pos ;  
  174.         break ;  
  175.     case 1: /*从文件当前位置开始偏移*/  
  176.         if((flip->f_pos + offset) > GLOBALMEM_SIZE ){  
  177.             ret = -EINVAL ;  
  178.             break ;  
  179.         }  
  180.         if((flip->f_pos + offset < 0)){  
  181.             ret = -EINVAL ;  
  182.             break ;  
  183.         }  
  184.         flip->f_pos += offset ;  
  185.         ret = flip->f_pos ;  
  186.         break ;  
  187.     default:  
  188.         return -EINVAL ;  
  189.     }  
  190.     return ret ;  
  191. }  
  192.   
  193. /*globalmem设备驱动的ioctl()函数*/  
  194. static int globalmem_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)  
  195. {  
  196.     struct globalmem_dev *dev = filp->private_data ;/*获取设备结构体指针*/  
  197.     switch(cmd){  
  198.     case CMD_CLEAR :  
  199.         /*清除全局变量*/  
  200.         memset(dev->mem,0,GLOBALMEM_SIZE) ;  
  201.         printk(KERN_INFO "globalmem is set to zero\n") ;  
  202.         break ;  
  203.     default:  
  204.         return -EINVAL ;/*其他不支持的命令*/  
  205.     }  
  206.     return 0 ;  
  207. }  
  208.   
  209. MODULE_AUTHOR("Hasen<hasen.dc@gmail.com>") ;  
  210. MODULE_LICENSE("Dual BSD/GPL") ;  
  211.   
  212. module_param(globalmem_major,int,S_IRUGO) ;  
  213.   
  214. module_init(globalmem_init) ;  
  215. module_exit(globalmem_exit) ;  
0 0
原创粉丝点击