Linux设备驱动入门----globalmem字符设备驱动

1、什么是globalmem虚拟设备

(1)、globalmem字符设备驱动中,分配一片内存大小为GLOBALMEM_SIZE(4K)的空间

(2)、提供对该片内存的读写、控制和定位函数

(3)、用户进程能够通过linux系统调用访问这篇内存

[cpp] view plaincopy
  1. #include <linux/module.h>  
  2. #include <linux/init.h>  
  3. #include <linux/types.h>  
  4. #include <linux/fs.h>  
  5. #include <linux/errno.h>  
  6. #include <linux/mm.h>  
  7. #include <linux/sched.h>  
  8. #include <linux/cdev.h>  
  9. #include <asm/io.h>  
  10. #include <asm/system.h>  
  11. #include <asm/uaccess.h>  
  12.   
  13. #define GLOBALMEM_SIZE 0X1000 /*全局内存最大4KB*/  
  14. #define MEM_CLEAR 0x1 /*清零全局内存*/  
  15. #define GLOBALMEM_MAJOR 254  /* 预设的globalmem 的主设备号 */
  16.   
  17. static globalmem_major = GLOBALMEM_MAJOR;/*预设的globalmem的主设备号*/  
  18.   
  19. /*globalmem的设备结构体:包含了对应于globalmem字符设备的cdev 和 使用内存mem[GLOBALMEM_SIZE]*/  
  20. struct globalmem_dev  
  21. {  
  22.  struct cdev cdev;  //cdev结构体  
  23.  unsigned char mem[GLOBALMEM_SIZE);  //全局内存  
  24. };  
  25.   
  26. struct globalmem_dev *globalmem_devp;  //设备结构体指针  
  27.   
  28. /*文件打开函数*/  
  29. int globalmem_open(struct inode *inode,struct file *filp)  
  30. {  
  31.  filp->private_data = globalmem_devp; //将设备结构体指针赋值给文件私有数据指针  
  32.  return 0  
  33. }  
  34.   
  35. /*文件释放函数*/  
  36. int globalmem_release(struct inode *inode,struct file *filp)  
  37. {  
  38.  return 0;  
  39. }  
  40.   
  41. /*设备控制函数:ioctl()函数接受的MEM_CLEAR命令,这个命令将全局内存的有效数据长度清零,对于设备不支持的命令,ioctl()函数应该返回-EINVAL*/  
  42. static int globalmen_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)  
  43. {  
  44.  struct globalmen_dev *dev = filp->private_data; //获得设备结构体指针  
  45.  switch(cmd)  
  46.  {  
  47.   case  MEE_CLEAR:  
  48.    memset(dev->mem,0,GLOBALMEM_SIZE);  
  49.    printk(KERN_INFO"globalmem is set to zero\n);  
  50.    break;  
  51.   default:  
  52.    return -EINVAL;  
  53.  }  
  54.  return 0;  
  55. }  
  56.   
  57. /*读函数:读写函数主要是让设备结构体的mem[]数组与用户空间交互数据,并随着访问字节数变更返回用户的文件读写偏移位置*/  
  58. static ssizez_t globalmem_read(struct file *filp,char __user *buf,size_t size,loff_t *opps)  
  59. {  
  60.  unsigned long p = *ppos;  
  61.  unsigned int count = size;  
  62.  int ret = 0;  
  63.  struct globalmem_dev *dev = filp->private_data; //获得设备结构体指针  
  64.    
  65.  if(p >= GLOBALMEM_SIZE)  //分析和获取有效的写长度  
  66.  {  
  67.   return count ? -ENXIO:0;  
  68.  }  
  69.  if(count > GLOBAL_SIZE - P)  
  70.  {  
  71.   count = GLOBALMEN_SIZE - P;  
  72.  }  
  73.    
  74.  if(copy_to_user(buf,(void *)(dev->mem+p),count))  //内核空间->用户空间  
  75.  {  
  76.   ret = -ENAU;T;  
  77.  }  
  78.  else  
  79.  {  
  80.   *oppos += count;  
  81.   ret = count;  
  82.   printk(KERN_INFO"read %d bytes(s) from %d\n",count,p);  
  83.  }  
  84.  return ret;  
  85. }  
  86.   
  87. /*写函数*/  
  88. static ssize_t globalmem_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)  
  89. {  
  90.  unsigned long *p = *ppos;  
  91.  unsigned int count = size;  
  92.  int ret;  
  93.    
  94.  struct globalmem_dev *dev = filp->private_data;  
  95.    
  96.  if(p >= CLOBALMEM_SIZE)  //分析和获取有效的写长度  
  97.  {  
  98.   return count? -ENXIO:0;  
  99.  }  
  100.    
  101.  if(count > GLOBALMEN_SIZE - P)  // 要写的字节数太多 
  102.  {  
  103.   count = CLOBALMEN_SIZE - P;  
  104.  }  
  105.    
  106.  if(copy_from_user(dev->mem + p,buf,count)) // 用户空间->内核空间  
  107.  {  
  108.   ret = -ENAULT;  
  109.  }  
  110.  else  
  111.  {  
  112.   *ppos =+ count;  
  113.   ret = count;  
  114.   printk(KERN_INFO"written %d bytes(s) from %d\n",count,p);  
  115.  }  
  116.  return ret;  
  117. }  
  118.   
  119. /*seek文件定位函数:seek()函数对文件定位的起始地址可以是文件开头(SEEK_SET,0)、当前位置(SEEK_CUR,1)、文件尾(SEEK_END,2)*/  
  120. static loff_t globalmem_llseek(struct file *filp,loff_t offset,int orig)  
  121. {  
  122.  loff_t ret = 0;  
  123.  switch(orig)  
  124.  {  
  125.   case 0:   //相对文件开始位置偏移  
  126.    if(offset <0 )  
  127.    {  
  128.     ret = -EINVAL;  
  129.     break;  
  130.    }  
  131.      
  132.    if((unsigned int )offset > GLOBALMEM_SIZE)  
  133.    {  
  134.     ret = - EINVAL;  
  135.     break;  
  136.    }  
  137.    filp->f_ops = (unsigned int)offset;  
  138.    ret = filp->f_pos;  
  139.    break;  
  140.      
  141.   case 1:   //相对文件当前位置偏移  
  142.    if((filp->f_ops + offset) > GLOBALMEMSIZE)  
  143.    {  
  144.     ret = -EINVAL;  
  145.     break;  
  146.    }  
  147.    if((filp->f_ops + offset)<0)  
  148.    {  
  149.     ret = -ENVAL;  
  150.     break;  
  151.    }  
  152.    filp->f_ops +=offset;  
  153.    ret = filp->f_ops;  
  154.    break;  
  155.   default:  
  156.    ret = -EINVAL;  
  157.    break;   
  158.  }  
  159.  return ret;  
  160. }  
  161.   
  162. /*文件操作结构体*/  
  163. static const struct file_operations globalmem_fops=  
  164. {  
  165.  .owner = THIS_MODULE;  
  166.  .llseek = globalmem_llseek;  
  167.  .read = globalmem_read;  
  168.  .write = globalmem_write;  
  169.  .ioctl = globalmem_ioctl;  
  170.  .open = globalmem_open;  
  171.  .release = globalmem_release;  
  172. };  
  173.   
  174. /*初始化并注册cdev*/  
  175. static void globalmem_setup_cdev(struct globalmem_dev *dev,int index)  
  176. {  
  177.  int err,devno = MKDEV(globalmen_major,index);  
  178.  cdev_init(&dev->cdev,&globalmem_fops);  
  179.  dev->cdev.owner = THIS_MOUDEL;  
  180.  dev->cdev.ops = &golbalmem_fops;  
  181.  err = cdev_add(&dev->cdev,devno,1);  
  182.  if(err)  
  183.  {  
  184.   printk(KERN_NOTICE"Error %d adding LED%d",err,index);  
  185.  }  
  186.    
  187. }  
  188.   
  189. /*设备驱动模块加载函数*/  
  190. static int __init globalmem_init(void)  
  191. {  
  192.  int result;  
  193.  dev_t devno = MKDEV(globalmem_major,0);  
  194.    
  195.  if(globalmem_major) //申请设备号  
  196.  {  
  197.   result = register_chrdev-region(devno,1,"globalmem");  
  198.  }  
  199.  else  //动态申请设备号  
  200.  {  
  201.   result = alloc_chrdev_region(&devno,0,1,"globalmem");  
  202.   globalmem_major = MAJOR(devno);  
  203.  }  
  204.    
  205.  if(result < 0)  
  206.  {  
  207.   return result;  
  208.  }  
  209.    
  210.  globalmem_devp = kmalloc(sizeof(struct globalmem_dev),GFP_KERNEL); //申请设备结构体的内存  
  211.  if(!globalmem_devp)  
  212.  {  
  213.   result = -ENOMEM;  
  214.   goto fail_malloc;  
  215.  }  
  216.    
  217.  memset(globalmem_devp,0,sizeof(struct globalmem_dev));  
  218.  globalmem_setup_cdev(globalmem_devp,0);  
  219.  return 0;  
  220.    
  221.  fail_malloc:unregister_chrdev_region(devno,1);  
  222.  return result;  
  223. }  
  224.   
  225. /*模块卸载函数*/  
  226. void __eixt globalmem_exit(void)  
  227. {  
  228.  cdev_del(&globalmem_devp->cdev); //注销cdev  
  229.  kfree(globalmem_devp);          //释放设备结构体内存  
  230.  unregister_chrdev_region(MKDEV(globalmem_major,0),1); //释放设备号  
  231. }  
  232.   
  233. MODULE_AUTHOR("NOODLE");  
  234. MODULE_LICENSE("GPL");  
  235.   
  236. mdule_param(globalmem_major,int,S_IRUGO);  
  237.   
  238. module_init(globalmem_init);  
  239. module_exit(globalmem_exit);   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401953.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百度地图iOS API

http://www.cnblogs.com/wengzilin/p/3444471.html http://blog.csdn.net/iukey/article/details/7343650转载于:https://www.cnblogs.com/nathanou/p/3556347.html

find_cmd函数分析

一、概述 1、函数位置 common/command.c 2、函数功能分析 解析命令的关键环节是如何根据输入命令查找对应命令的信息&#xff0c;从而跳转到对应命令的函数处执行程序。这必然涉及到如何存放命令的详细信息这个问题。因为一种存法&#xff0c;对应一种查法&#xff0c;进…

ARM 指令集 VS Thumb 指令集

Thumb指令集Thumb指令可以看做是ARM指令压缩形式的子集&#xff0c;是针对代码密度【1】的问题而提出的&#xff0c;它具有16为的代码密度。Thumb不是一个完整的体系结构&#xff0c;不能指望处理程序只执行Thumb指令而不支持ARM指令集。因此&#xff0c;Thumb指令只需要支持通…

软件测试 -- alpha测试和beta测试的区别

alpha测试是在用户组织模拟软件系统的运行环境下的一种验收测试,由用户或第三方测试公司进行的测试,模拟各类用户行为对即将面市的软件产品进行测试,试图发现并修改错误。 Beta测试是用户公司组织各方面的典型终端用户在日常工作中实际使用beta版本,并要求用户报告异常情况,…

Linux 驱动头文件说明

#include <linux/***.h> //是在linux-2.6.29/include/linux下面寻找源文件。 #include <asm/***.h> //是在linux-2.6.29/arch/arm/include/asm下面寻找源文件。 #include <mach/***.h> //是在lin…

ACL访问控制

ACL访问控制概述&#xff1a;访问控制&#xff0c;当文件或目录的权限不能在完全满足访问控制的实现时&#xff0c;可以使用acl进行设置访问权限。即&#xff0c;对一个文件或者目录设置个别&#xff08;特殊&#xff09;用户对其有操作的权限ACL访问控制的作用&#xff1a;1&a…

内联函数 —— C 中关键字 inline 用法解析

一、什么是内联函数 在C语言中&#xff0c;如果一些函数被频繁调用&#xff0c;不断地有函数入栈&#xff0c;即函数栈&#xff0c;会造成栈空间或栈内存的大量消耗。 为了解决这个问题&#xff0c;特别的引入了inline修饰符&#xff0c;表示为内联函数。 栈空间就是指放置程式…

eclipse maven scm

http://my.oschina.net/OutOfMemory/blog/178512 1.安装eclipse的maven插件 m2e(http://wiki.eclipse.org/M2E_updatesite_and_gittags)Help->Install New Software...在work with中填入我们需要安装m2e的版本url&#xff1a;http://download.eclipse.org/technology/m2e/…

DS18B20 驱动编写

嵌入式开发平台&#xff1a;mini2440 DS18B20 所用GPIO&#xff1a;S3C2410_GPF(3) 一、DS18B20 时序分析 DS18B20的一线工作协议流程是&#xff1a;初始化→ROM操作指令→存储器操作指令→数据传输&#xff0c;其工作时序包括&#xff1a;初始化时序、写时序、读时序。 1、初…

Android 自定义View实现画背景和前景(ViewGroup篇)

2019独角兽企业重金招聘Python工程师标准>>> 在定义ListView的Selector时候&#xff0c;有个drawSelectorOnTop的属性&#xff0c;如果drawSelectorOnTop为true的话&#xff0c;Selector的效果是画在List Item的上面&#xff08;Selector是盖住了ListView的文字或者…

Linux的mmap内存映射机制解析

在讲述文件映射的概念时,不可避免的要牵涉到虚存(SVR 4的VM).实际上,文件映射是虚存的中心概念, 文件映射一方面给用户提供了一组措施,好似用户将文件映射到自己地址空间的某个部分,使用简单的内存访问指令读写文件&#xff1b;另一方面,它也可以用于内核的基本组织模式,在这种…

svn add Default@2x.png的文件含有@的文件名注意事项

为什么80%的码农都做不了架构师&#xff1f;>>> iOS的Icon里面&#xff0c;包含符号 &#xff0c;svn add Icon2x.png&#xff0c;没法加进去。 解决的办法是&#xff0c;在文件名最后加一个&#xff0c;例如 svn add Icon2x.png 或者svn add Icon\2x.png\ 转载于…

Linux 设备驱动的固件加载

作为一个驱动作者, 你可能发现你面对一个设备必须在它能支持工作前下载固件到它里面. 硬件市场的许多地方的竞争是如此得强烈, 以至于甚至一点用作设备控制固件的 EEPROM 的成本制造商都不愿意花费. 因此固件发布在随硬件一起的一张 CD 上, 并且操作系统负责传送固件到设备自身…

ORM for Net主流框架汇总与效率测试

框架已经被越来越多的人所关注与使用了&#xff0c;今天我们就来研究一下net方面的几个主流ORM框架&#xff0c;以及它们的效率测试&#xff08;可能会有遗漏欢迎大家讨论&#xff09;。 ORM框架&#xff1a;Object/Relation Mapping&#xff08;对象/关系 映射&#xff09;的缩…

Yii基于角色的访问控制(非Rbac)

今天遇到了权限控制的问题&#xff0c;后台不同级别的用户登录后看到的内容是不一样的。网上查了下&#xff0c;说Yii中有自带的RBAC权限控制&#xff0c;大概看了下&#xff0c;没理解太明白。然后就是采用filter进行过滤验证&#xff0c;看着这个还不错。下面简单说下我是我怎…

Linux USB 驱动开发(二)—— USB 驱动几个重要数据结构

前面我们学习了USB 驱动的一个描述符&#xff0c;下面来学习 USB 驱动的几个重要数据结构 一、struct usb_interface 接口函数 [cpp] view plaincopy struct usb_interface { struct usb_host_interface *altsetting; struct usb_host…

比较DataTable中新旧数据

内容不写了&#xff0c;代码上都做了写注释。1 /** <summary> 2 /// 比较两个数据表&#xff0c;并返回比较结果表 3 /// 比较条件&#xff1a; 4 /// 1.两个表结构相同&#xff1b; 5 /// 2.两个表排序都是按主键顺序排序&#xff1b…

Linux USB 驱动开发(三)—— 编写USB 驱动程序

前面学习了USB驱动的一些基础概念与重要的数据结构&#xff0c;那么究竟如何编写一个USB 驱动程序呢&#xff1f;编写与一个USB设备驱动程序的方法和其他总线驱动方式类似&#xff0c;驱动程序把驱动程序对象注册到USB子系统中&#xff0c;稍后再使用制造商和设备标识来判断是否…

病毒式推广最终可能会走到尽头

Buzzfeed自称是社交时代的媒体(The Media of Social Age)&#xff0c;而HuffingtonPost是为搜索引擎创作的。我们也曾经读过《 Believe Me, I’m Lying》这样的关于如何通过博客操纵媒体的书。在社交时代&#xff0c;资讯会发生什么样的变化&#xff1f;FT 约翰•加普的文章为我…

Linux USB 驱动开发(一)—— USB设备基础概念

在终端用户看来&#xff0c;USB设备为主机提供了多种多样的附加功能&#xff0c;如文件传输&#xff0c;声音播放等&#xff0c;但对USB主机来说&#xff0c;它与所有USB设备的接口都是一致的。一个USB设备由3个功能模块组成&#xff1a;USB总线接口、USB逻辑设备和功能单元&am…