驱动:

  1. #include <linux/module.h>
  2. #include <linux/types.h>
  3. #include <linux/fs.h>
  4. #include <linux/errno.h>
  5. #include <linux/mm.h>
  6. #include <linux/sched.h>
  7. #include <linux/init.h>
  8. #include <linux/cdev.h>
  9. #include <asm/io.h>
  10. #include <asm/system.h>
  11. #include <asm/uaccess.h>
  12. #include <linux/slab.h>
  13. #include <linux/device.h>
  14.  
  15. #ifndef MEMDEV_MAJOR
  16. #define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/
  17. #endif
  18.  
  19. #ifndef MEMDEV_NR_DEVS
  20. #define MEMDEV_NR_DEVS 2 /*设备数*/
  21. #endif
  22.  
  23. #ifndef MEMDEV_SIZE
  24. #define MEMDEV_SIZE 4096
  25. #endif
  26.  
  27. #define DEVICE_NAME "memdev"
  28.  
  29. /*udev自动添加设备节点*/
  30. struct class *mem_class;
  31.  
  32. static int mem_major = MEMDEV_MAJOR;
  33.  
  34. module_param(mem_major, int, S_IRUGO);
  35.  
  36. struct mem_dev
  37. {
  38. struct cdev cdev; /*cdev结构体*/
  39. unsigned char mem[MEMDEV_SIZE]; /*全局内存*/
  40. };
  41.  
  42. struct mem_dev *mem_devp; /*设备结构体指针*/
  43.  
  44. /*文件打开函数*/
  45. int mem_open(struct inode *inode, struct file *filp)
  46. {
  47. struct mem_dev *dev;
  48.  
  49. dev=container_of(inode->i_cdev,struct mem_dev,cdev);//通过结构体成员的指针找到对应结构体的指针
  50.  
  51. /*将设备描述结构指针赋值给文件私有数据指针*/
  52. filp->private_data = dev;
  53.  
  54. return ;
  55. }
  56.  
  57. /*文件释放函数*/
  58. int mem_release(struct inode *inode, struct file *filp)
  59. {
  60. return ;
  61. }
  62.  
  63. /*读函数*/
  64. static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
  65. {
  66. unsigned long p = *ppos;
  67. unsigned int count = size;
  68. int ret = ;
  69. struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/
  70.  
  71. /*判断读位置是否有效*/
  72. if (p >= MEMDEV_SIZE)
  73. return ;
  74. if (count > MEMDEV_SIZE - p)
  75. count = MEMDEV_SIZE - p;
  76.  
  77. /*读数据到用户空间*/
  78. if (copy_to_user(buf, (void*)(dev->mem+ p), count))
  79. {
  80. ret = - EFAULT;
  81. }
  82. else
  83. {
  84. *ppos += count;
  85. ret = count;
  86.  
  87. printk(KERN_INFO "read %d bytes(s) from postion %d\n", count, p);
  88. }
  89.  
  90. return ret;
  91. }
  92.  
  93. /*写函数*/
  94. static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
  95. {
  96. unsigned long p = *ppos;
  97. unsigned int count = size;
  98. int ret = ;
  99. struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/
  100.  
  101. /*分析和获取有效的写长度*/
  102. if (p >= MEMDEV_SIZE)
  103. return ;
  104. if (count > MEMDEV_SIZE - p)
  105. count = MEMDEV_SIZE - p;
  106.  
  107. /*从用户空间写入数据*/
  108. if (copy_from_user(dev->mem + p, buf, count))
  109. ret = - EFAULT;
  110. else
  111. {
  112. *ppos += count;
  113. ret = count;
  114.  
  115. printk(KERN_INFO "written %d bytes(s) to postion %d\n", count, p);
  116. }
  117.  
  118. return ret;
  119. }
  120.  
  121. /* seek文件定位函数 */
  122. static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
  123. {
  124. loff_t newpos;
  125.  
  126. switch(whence) {
  127. case : /* SEEK_SET */
  128. newpos = offset;
  129. break;
  130.  
  131. case : /* SEEK_CUR */
  132. newpos = filp->f_pos + offset;
  133. break;
  134.  
  135. case : /* SEEK_END */
  136. newpos = MEMDEV_SIZE - + offset;
  137. break;
  138.  
  139. default: /* can't happen */
  140. return -EINVAL;
  141. }
  142. if ((newpos<) || (newpos>MEMDEV_SIZE))
  143. return -EINVAL;
  144.  
  145. filp->f_pos = newpos;
  146. return newpos;
  147.  
  148. }
  149.  
  150. /*文件操作结构体*/
  151. static const struct file_operations mem_fops =
  152. {
  153. .owner = THIS_MODULE,
  154. .llseek = mem_llseek,
  155. .read = mem_read,
  156. .write = mem_write,
  157. .open = mem_open,
  158. .release = mem_release,
  159. };
  160.  
  161. /*初始化并注册cdev*/
  162. static void mem_setup_cdev(struct mem_dev *dev, int index)
  163. {
  164. int err, devno = MKDEV(mem_major, index);
  165.  
  166. cdev_init(&dev->cdev, &mem_fops);
  167. dev->cdev.owner = THIS_MODULE;
  168. dev->cdev.ops = &mem_fops;
  169. err = cdev_add(&dev->cdev, devno, );
  170. if (err)
  171. printk(KERN_NOTICE "Error %d adding LED%d", err, index);
  172. }
  173.  
  174. /*设备驱动模块加载函数*/
  175. static int memdev_init(void)
  176. {
  177. int result;
  178.  
  179. dev_t devno = MKDEV(mem_major, );
  180.  
  181. /* 静态申请设备号*/
  182. if (mem_major)
  183. result = register_chrdev_region(devno, MEMDEV_NR_DEVS, DEVICE_NAME);
  184. else /* 动态分配设备号 */
  185. {
  186. result = alloc_chrdev_region(&devno, , MEMDEV_NR_DEVS, DEVICE_NAME);
  187. mem_major = MAJOR(devno);
  188. }
  189.  
  190. if (result < )
  191. return result;
  192.  
  193. /* 为设备描述结构分配内存*/
  194. mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);
  195. if (!mem_devp) /*申请失败*/
  196. {
  197. result = - ENOMEM;
  198. goto fail_malloc;
  199. }
  200. memset(mem_devp, , *sizeof(struct mem_dev));
  201.  
  202. /*为设备分配内存*/
  203. mem_setup_cdev(&mem_devp[], );
  204. mem_setup_cdev(&mem_devp[], );
  205.  
  206. /*udev机制可以自动添加设备节点,只需要添加xxx_class这个类,以及device_create()*/
  207. mem_class = class_create(THIS_MODULE, "mem_class");/*在sys目录下创建xx_class这个类,/sys/class/~*/
  208. device_create(mem_class, NULL, mem_devp[].cdev.dev, NULL, "memdev0");/*自动创建设备/dev/$DEVICE_NAME*/
  209. device_create(mem_class, NULL, mem_devp[].cdev.dev, NULL, "memdev1");/*自动创建设备/dev/$DEVICE_NAME*/
  210.  
  211. printk("memdev driver installed, with major %d\n", mem_major);
  212. printk("the device name is %s\n",DEVICE_NAME);
  213. return ;
  214.  
  215. fail_malloc:
  216. unregister_chrdev_region(devno, );
  217.  
  218. return result;
  219. }
  220.  
  221. /*模块卸载函数*/
  222. static void memdev_exit(void)
  223. {
  224.  
  225. device_destroy(mem_class, mem_devp[].cdev.dev);
  226. device_destroy(mem_class, mem_devp[].cdev.dev);
  227. class_destroy(mem_class);
  228. cdev_del(&(mem_devp[].cdev)); /*注销设备*/
  229. cdev_del(&(mem_devp[].cdev));
  230.  
  231. kfree(mem_devp); /*释放设备结构体内存*/
  232. unregister_chrdev_region(MKDEV(mem_major, ), ); /*释放设备号*/
  233. printk("memdev driver uninstalled\n");
  234. }
  235.  
  236. MODULE_AUTHOR("mhb@SEU");
  237. MODULE_LICENSE("GPL");
  238.  
  239. module_init(memdev_init);
  240. module_exit(memdev_exit);

测试代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5.  
  6. #include <string.h>
  7.  
  8. int main()
  9. {
  10. FILE *fp0 = NULL;
  11. char Buf[];
  12. int result;
  13.  
  14. /*初始化Buf*/
  15. strcpy(Buf,"Mem is char dev!");
  16. printf("BUF: %s\n",Buf);
  17.  
  18. /*打开设备文件*/
  19. fp0 = fopen("/dev/memdev0","r+");
  20. if (fp0 == NULL)
  21. {
  22. perror("Open Memdev0 Error!\n");
  23. return -;
  24. }
  25.  
  26. /*写入设备*/
  27. result = fwrite(Buf, sizeof(Buf), , fp0);
  28. if (result == -)
  29. {
  30. perror("fwrite Error!\n");
  31. return -;
  32. }
  33.  
  34. /*重新定位文件位置(思考没有该指令,会有何后果)*/
  35. fseek(fp0,,SEEK_SET);
  36.  
  37. /*清除Buf*/
  38. strcpy(Buf,"Buf is NULL!");
  39. printf("BUF: %s\n",Buf);
  40.  
  41. sleep();
  42. /*读出设备*/
  43. result = fread(Buf, sizeof(Buf), , fp0);
  44. if (result == -)
  45. {
  46. perror("fread Error!\n");
  47. return -;
  48. }
  49.  
  50. /*检测结果*/
  51. printf("BUF: %s\n",Buf);
  52.  
  53. return ;
  54.  
  55. }

虚拟内存设备驱动memdev及实例代码的更多相关文章

  1. [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计

    目       录 第三章           设备驱动的设计... 2 3.1           初始化设备... 4 3.2           运行设备接口设计... 4 3.3        ...

  2. linux设备驱动概述,王明学learn

    linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...

  3. Linux高级字符设备驱动

    转载:http://www.linuxidc.com/Linux/2012-05/60469p4.htm 1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select ...

  4. Linux高级字符设备驱动 poll方法(select多路监控原理与实现)

    1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程.      int selec ...

  5. 乾坤合一~Linux设备驱动之I2C核心、总线以及设备驱动

    我思念的城市已是黄昏 为何我总对你一往情深 曾经给我快乐 也给我创伤 曾经给我希望 也给我绝望 我在遥远的城市 陌生的人群 感觉着你遥远的忧伤 我的幻想 你的忧伤,像我的的绝望,那样漫长,,,,,这是 ...

  6. RT thread 设备驱动组件之USART设备

    本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...

  7. Linux字符设备驱动实例—globalmem驱动

    1.globalmem虚拟设备实例 globalmem为“全局内存”的意思,在globalmem字符设备中会分配一片大小为GLOBALMEM_SIZE(4KB)的内存空间,并在驱动中提供对这片内存的读 ...

  8. linux设备驱动第四篇:从如何定位oops的代码行谈驱动调试方法

    上一篇我们大概聊了如何写一个简单的字符设备驱动,我们不是神,写代码肯定会出现问题,我们需要在编写代码的过程中不断调试.在普通的c应用程序中,我们经常使用printf来输出信息,或者使用gdb来调试程序 ...

  9. 《连载 | 物联网框架ServerSuperIO教程》- 14.配制工具介绍,以及设备驱动、视图驱动、服务实例的挂载

    注:ServerSuperIO二次开发套件授权码申请---截止到:2016-12-09 1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架Server ...

随机推荐

  1. Linux-PAM(Linux下的密碼認證和安全机制)系統管理員指南(中文版)

    he Linux-PAM 系统管理员指南作者:Andrew G. Morgan, morgan@linux.kernel.org翻译:孙国清(Thomas Sun),thomassun@yeah.ne ...

  2. Hadoop可视化与交互式工具:Zeppelin和Hue

    https://yq.aliyun.com/articles/42282?spm=5176.team18.teamshow1.19.9TkKmZ#rd

  3. Validation

    Validation A simple but powerful Validation Engine, in a Laravel-esque style. Its Validation Rules a ...

  4. swift switch语句

    switch选择 1)case多条件匹配:条件之间用逗号隔开 用三个点表示范围:…,..<:表示不包含上边界 var tand = 1 switch tand{    case 0:       ...

  5. MySQL创建/删除/清空表,添加/删除字段

    创建表: create table tablename (column_name column_type); create table table_name( id int not null auto ...

  6. ubuntu 安装 JVM 与 ElasticSearch

    测试环境: Ubuntu x86_64 3.13.0-35-generic 安装jre: $ sudo apt-get install software-properties-common $ sud ...

  7. N_F1_APPROVE

    package nc.bs.pub.action; import java.util.ArrayList; import java.util.Hashtable; import java.util.L ...

  8. 【JavaScript权威指南(第五版)】笔记之第二部分 客户端JavaScript 第13章~第23章

    第十三章 Web浏览器中的javascript ①   eg:下面两行代码实际上执行的是相同的功能 var answer = 42; window.answer = 42;   ③每个window对象 ...

  9. 20160503-spring入门1

    一.Spring是什么 Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发. IOC 控制反转  publ ...

  10. 初试zabbix

    一.zabbix简介    zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.       zabbix由zabbix server与可选组件zabbix a ...