代码如下

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/cdev.h>
  5. #include <linux/fs.h>
  6. #include <linux/device.h>
  7.  
  8. int demo_major = ;
  9. int demo_minor = ;
  10. int demo_count = ;
  11.  
  12. struct cdev cdev;
  13.  
  14. static struct class *demo_class;
  15. static struct device *demo_device;
  16.  
  17. int demo_open(struct inode *inodep, struct file * filep) // 打开设备
  18. {
  19. printk("%s,%d\n", __func__, __LINE__);
  20. return ;
  21. }
  22.  
  23. int demo_release(struct inode * inodep, struct file * filep) // 关闭设备
  24. {
  25. printk("%s,%d\n", __func__, __LINE__);
  26. return ;
  27. }
  28.  
  29. struct file_operations fops =
  30. {
  31. .owner = THIS_MODULE,
  32. .open = demo_open,
  33. .release = demo_release,
  34. };
  35.  
  36. static int __init demo_init(void)
  37. {
  38. int ret = ;
  39. dev_t devno;
  40.  
  41. printk("%s,%d\n", __func__, __LINE__);
  42.  
  43. //使用下列宏则可以通过主设备号和次设备号生成 dev_t
  44. devno = MKDEV(demo_major, demo_minor);
  45.  
  46. printk("devno:%d\n", devno);
  47. printk("demo_major:%d\n", demo_major);
  48.  
  49. /**在调用 cdev_add()函数向系统注册字符设备之前,
  50. *应首先调用 register_chrdev_region()或alloc_chrdev_region()函数向系统申请设备号
  51. **/
  52. if (demo_major)
  53. {
         //使用cat /proc/devices | grep demo 来查询
  54. ret = register_chrdev_region(devno, , "demo");
  55. }
  56. else
  57. {
  58. ret = alloc_chrdev_region(&devno, demo_minor, , "demo");
  59. }
  60.  
  61. if(ret)
  62. {
  63. printk("Failed to register_chrdev_region.\n");
  64. return ret;
  65. }
  66.  
  67. //cdev_init()函数用于初始化 cdev 的成员,并建立 cdev 和 file_operations 之间的连接
  68. cdev_init(&cdev, &fops);
  69. cdev.owner = THIS_MODULE;
  70.  
  71. //系统添加一个 cdev,完成字符设备的注册。
  72. ret = cdev_add(&cdev, devno, demo_count);
  73. if(ret)
  74. {
  75. printk(KERN_NOTICE " Failed to cdev_add [Error] %d adding demo%d", ret, demo_minor);
  76.  
  77. goto failure_cdev_add;
  78.  
  79. }
  80.  
  81. /*自动创建设备节点文件*/
  82.  
  83. //1.注册设备类 /sys/class/demo的文件夹
      //使用 ls /sys/class/demo
  84. demo_class = class_create(THIS_MODULE, "demo");
  85. if( IS_ERR(demo_class))
  86. {
  87. printk("class_create failed!\n");
  88. ret = PTR_ERR("demo_class");
  89. goto failure_class_create;
  90. }
  91.  
  92. //2.注册设备 /sys/class/demo/demo0 /dev/demo0
  93. demo_device = device_create(demo_class, NULL, MKDEV(demo_major, demo_minor), NULL, "demo%d", demo_minor);
  94. if(IS_ERR(demo_device)){
  95. printk("device_create failed!\n");
  96. ret = PTR_ERR("demo_device");
  97. goto failure_device_create;
  98. }
  99. return ;
  100.  
  101. failure_device_create:
  102. class_destroy(demo_class);
  103. failure_class_create:
  104. cdev_del(&cdev);
  105. failure_cdev_add:
  106. unregister_chrdev_region(devno, demo_count);
  107. failure_register_chrdev:
  108. return ret;
  109. }
  110.  
  111. static void __exit demo_exit(void)
  112. {
  113. printk("%s,%d\n", __func__, __LINE__);
  114.  
  115. /*逆序消除*/
  116. //从内核中删除设备
  117. device_destroy(demo_class,MKDEV(demo_major, demo_minor));
  118. //从内核中删除设备类
  119. class_destroy(demo_class);
  120. //删除一个 cdev,完成字符设备的注销。
  121. cdev_del(&cdev);
  122. //在调用cdev_del()函数从系统注销字符设备之后,unregister_chrdev_region()应该被调用以释放原先申请的设备号
  123. unregister_chrdev_region( MKDEV(demo_major, demo_minor), demo_count );
  124. }
  125.  
  126. module_init(demo_init);
  127. module_exit(demo_exit);
  128.  
  129. MODULE_AUTHOR(" libra13179 ");
  130. MODULE_LICENSE("GPL v2");
  1. KVERS = $(shell uname -r)
  2.  
  3. # Kernel modules
  4. obj-m += demo.o
  5.  
  6. # Specify flags for the module compilation.
  7. #EXTRA_CFLAGS=-g -O0
  8.  
  9. build: kernel_modules
  10.  
  11. kernel_modules:
  12. make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
  13. # @echo $(KVERS)
  14.  
  15. clean:
  16. make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
  1. #include <sys/types.h>
  2.  
  3. #include <sys/stat.h>
  4.  
  5. #include <fcntl.h>
  6.  
  7. #include <stdio.h>
  8.  
  9. int main(int argc, const char *argv[])
  10.  
  11. {
  12.  
  13. int fd;
  14.  
  15. int val = ;
  16.  
  17. fd = open("/dev/demo0", O_RDWR);
  18.  
  19. if (fd < )
  20.  
  21. {
  22.  
  23. printf("can't open!\n");
  24.  
  25. return -;
  26.  
  27. }
  28.  
  29. else
  30.  
  31. {
  32.  
  33. printf("open success.\n");
  34.  
  35. }
  36.  
  37. getchar();
  38.  
  39. close(fd);
  40.  
  41. return ;
  42.  
  43. }

主要使用到函数

  1. class_create
  1. device_create
  1. device_destroy
  2.  
  3. class_destroy
  4.  
  5. 小技巧:
  1. 类似
    http://lxr.free-electrons.com/
    http://lxr.oss.org.cn/
    这样的网站提供了Linux内核源代码的交叉索引,
    在其中输入Linux内核中的函数、数据结构或变量的名称就可以直接得到以超链接形式给出的定义和引用它的所有位置。
    还有一些网站也提供了Linux内核中函数、变量和数据结构的搜索功能,
    google中搜索“linux identifier search”可得。
  1.  

linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)的更多相关文章

  1. class_create(),device_create自动创建设备文件结点

    class_create(),device_create自动创建设备文件结点 从linux 内核2.6的某个版本之后,devfs不复存在,udev成为devfs的替代.相比devfs,udev有很多优 ...

  2. GPIO硬件资源的申请,内核空间和用户空间的数据交换,ioctl(.....),设备文件的自动创建

    1.通过GPIO库函数控制LED   open("/dev/myleds",...)       close(fd)   ----------------------------- ...

  3. platform型设备在/dev目录下自动创建设备节点的分析【转】

    转自:http://blog.csdn.net/rockrockwu/article/details/7357648 系统启动过程中platform设备.驱动注册完毕,为什么在/dev目录下就自动创建 ...

  4. Linux驱动开发2——字符设备驱动

    1.申请设备号 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char ...

  5. 初入android驱动开发之字符设备(四-中断)

    上一篇讲到android驱动开发中,应用是怎样去操作底层硬件的整个流程,实现了按键控制led的亮灭.当然,这是一个非常easy的实例,只是略微演变一下,就能够得到广泛的应用. 如开发扫描头,应用透过监 ...

  6. 初入android驱动开发之字符设备(一)

    大学毕业,初入公司,招进去的是android驱动开发工程师的岗位,那时候刚进去,首先学到的就是如何搭建kernel.android的编译环境,然后就是了解如何刷设备以及一些最基本的工具.如adb.fa ...

  7. 驱动开发--【字符设备、块设备简介】【sky原创】

    驱动开发   字符设备,块设备,网络设备   字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问   EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...

  8. linux设备驱动第四篇:驱动调试方法

    http://www.cnblogs.com/donghuizaixian/archive/2015/04/02/4387083.html 上一篇我们大概聊了如何写一个简单的字符设备驱动,我们不是神, ...

  9. linux设备驱动----利用mdev(udev)自动创建设备文件节点

    1.mdev的使用方法和原理: mdev是busybox 自带的一个简化版的udev,适合于嵌入式的应用埸合.其具有使用简单的特点.它的作用,就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程 ...

随机推荐

  1. SpringSecurity-SecurityContextPersistenceFilter的作用

    SecurityContextPersistenceFilter每个request只执行一次,以解决servlet容器的兼容性问题(特别是WebLogic). 它在request执行之前从Securi ...

  2. java浅析final关键字

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...

  3. 知识点-jar包

    JAR文件的全称是Java Archive File,意思就是Java档案文件.通常JAR文件是一种压缩文件,与常见的ZIP压缩文件兼容,同城也被称为JAR包.JAR文件与zip文件的去区别就是在JA ...

  4. C#连接Access数据库显示未在本地计算机注册解决方法

    C#连接数据库时会出错 语句如下 string mystr = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Users\hasee ...

  5. 定位cpu内存问题

    定位cpu内存问题 ps -Hp pid  显示进程的线程,P 按CPU内存排序 jstack pid>pid.log 将线程栈 dump 到日志文件中 线程号 十进制转换为 十六进制 在文件中 ...

  6. orcale 函数wm_concat不存咋lob值使用zh_concat 替换

    create or replace TYPE zh_concat_im AUTHID CURRENT_USER AS OBJECT ( CURR_STR VARCHAR2(32767), STATIC ...

  7. 在Docker中安装配置Oracle12c并实现数据持久化

    在Docker中安装配置Oracle12c并实现数据持久化 选定镜像,并pull到系统中,一定要先配置加速,不然超级慢 eric@userver:~$ docker pull sath89/oracl ...

  8. linux系统配置jdk环境

    前提:linux服务器+JDK8-linux版本 工具:FileZilla+Xshell 将jdk上传到服务器的某个文件夹(本人是JDK) 进入该文件夹,输入tar xzvf  jdk-8u77-li ...

  9. 小众Python库介绍

    Python 是世界上发展最快的编程语言之一.它一次又一次地证明了自己在开发人员和跨行业的数据科学中的实用性.Python 及其机器学习库的整个生态系统使全世界的用户(无论新手或老手)都愿意选择它.P ...

  10. CS229 7.2 应用机器学习方法的技巧,准确率,召回率与 F值

    建立模型 当使用机器学习的方法来解决问题时,比如垃圾邮件分类等,一般的步骤是这样的: 1)从一个简单的算法入手这样可以很快的实现这个算法,并且可以在交叉验证集上进行测试: 2)画学习曲线以决定是否更多 ...