linux设备驱动开发学习之旅--使用文件私有数据的字符设备驱动_嵌入式Linux那些事的博客-程序员秘密

技术标签: 驱动  

[cpp]  view plain copy 在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<[email protected]>") ;  
  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) ;  
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhoudengqing/article/details/41485637

智能推荐

python中list和dict之间的转换_Cherls的博客-程序员秘密

列表转换成字典注:列表不能直接使用dict转换成字典。方法一:使用zip()函数a = ['a1','a2','a3','a4']b = ['b1','b2','b3']d = zip(a,b)print(dict(d)) # {'a1': 'b1', 'a2': 'b2', 'a3': 'b3'}将...

fetch()函数_caiqm_kid的博客-程序员秘密

Fetch()方法获取结果集中的下一行数据,语法如下:Mixed PDOStatement::fetch([int fetch_style [,int cursor_orientation[,int cursor_offset]]])参数fetch_style:控制结果集的返回方式,其可选值如下:PDO::FETCH_ASSOC  关联数组形式PDO::FETCH_NUM    数

Tensor维度变换_图像由三维tensor转为四维tensor_越来越胖了_mengleijin的博客-程序员秘密

Tensor维度变换有点意思1 view/reshape先来个4维tensor,实际意义是一个4张图片,通道一个,就是灰度图片,然后长宽都是28的图片它的shape这个样子这个直接给怼成了2维的,一个 4 x 784reshape和view一个功能其实完全随意可以升降维,但是要还原的话,shape的顺序要对,不然就不是原来的数据, 看看c和d就明白了还有最好是用这种,si...

【读书笔记】代码大全28章:项目管理_whitejava2的博客-程序员秘密

鼓励良好的编码习惯制定编码规范使用灵活的编码规范鼓励良好编码规范项目的每个部分都分配两个人审查每一行代码做好代码验收工作将好的代码用来审查强调“代码属于大家”程序员写了良好的代码要给予奖励给程序员想要的东西“良好”指的是特别好,大家都认可的“好”制定单个简单的标准比如:我必须能读懂项目中的一切代码本书的目标:提供良好的编码规范配置管理

想学明白PostgreSQL,得先捋一捋体系架构_postgres 的架构 dba映射图_IT邦德的博客-程序员秘密

本文对PostgreSQL的体系架构做了详细的阐述,希望对大家有所帮助

1.创建企业微信自建应用_a1350793的博客-程序员秘密

1.注册企业微信》应用管理》创建应用》  1.1 设置工作带应用主页     构造网页授权连接 详细请查看微信官方文档:https://work.weixin.qq.com/api/doc#90000/90135/91022 https://open.weixin.qq.com/connect/oauth2/autho...

随便推点

Android源码编译全过程记录(基于最新安卓5.1.0)【转】_weixin_34355715的博客-程序员秘密

本文转载自:http://blog.csdn.net/drg1612/article/details/44802533我的编译条件:1 Ubuntu Kylin 14.04 长期支持版 下载地址 : http://www.ubuntu-china.cn/download2 我的电脑是联想G470 i3处理器 内存4G,120g固体硬盘,配置不高,但是足够编译了(编译花费了5小时)3...

bat脚本 _YB程序员的博客-程序员秘密

1:cd /d %~dp0比如你有个批处理a.bat在D:\test文件夹下 a.bat内容为  cd /d %~dp0在这里cd /d 表示直接转换到后面的路径,否则如果切换盘符,就需要再输入盘符才能切换路径cd /d %~dp0的意思就是cd /d d:\test %0代表批处理本身 d:\test\a.bat ~dp是变量扩充 d既是扩充到分区号 d: p就是扩充到路径 \tes...

情人节海报psd分层模板|好的图层,任你选择_awayaya1的博客-程序员秘密

每到情人节,全世界的商家都在告诉你。“情人节不送礼物就是无耻。”什么行业都告诉你,情人节要买它们的产品。不管是美容、孕婴、服装、家用、生鲜还是金融……但我觉得,爱情不需要太多礼物,更需要的是相互表达。这个时候,这也意味着各位设计师又有得忙了,又是做海报,又是搞banner的。下面作为平面素材网站的素材路上 www.sucai63.com 便给大家带来一些情人节主题的平面设计灵感,满屏的粉红泡泡,看着都荡漾了——PSD分层格式的模板,想要图层中的任意元素,只要选择该图层,直接拖拽到自己

csdn,我来了_canmida的博客-程序员秘密

呵呵,虽然注册了这么久,可就是没有写过东西!今天是个开始。本来工作上有点不顺心,可是,下班了就不想了。“一天的愁苦一天当就够了”。

Web开发中防止程序出现漏洞的一些有效手段_wang_quan_li的博客-程序员秘密

如今的Web应用程序可能会包含危险的安全缺陷。这些应用程序的全球化部署使其很容易遭受攻击,这些攻击会发现并恶意探测各种安全漏洞。  Web环境中两个主要的风险在于:注入——也就是SQL注入,它会让黑客更改发往数据库的查询——以及跨站脚本攻击(XSS),它们也是最危险的 (Category:OWASP_Top_Ten_Project)。注入攻击会利用有问题代码的应用程序来插入和执行黑客指

UVA136 丑数_丑数uva 136_calamity_coming的博客-程序员秘密

题目的意思是要输出第1500个丑数