linux驱动开发(十)——misc杂散设备

发布者:静心静气最新更新时间:2025-02-18 来源: cnblogs关键字:linux  驱动开发  misc 手机看文章 扫描二维码
随时随地手机看文章

1:什么是misc驱动模型?

2:为什么要有misc驱动模型?

3:misc驱动模型的代码实现

4:misc驱动模型实战

参考:

http://blog.csdn.net/yicao821/article/details/6785738

http://www.thinksaas.cn/topics/0/507/507168.html

http://www.cnblogs.com/fellow1988/p/6235080.html

https://www.zhihu.com/question/21508904

http://www.cnblogs.com/snake-hand/p/3212483.html

http://blog.csdn.net/chenlong12580/article/details/7339127

--------------------------------------------------------------------------------------------------------------------------------------------------------------

1:什么是misc驱动模型

  Linux包含了许多的设备驱动类型,而不管分类有多细,总会有些漏网的,这就是我们经常说到的“其他的”等等。
在Linux里面,把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体来描述)。Linux/内核所提供的miscdevice有很强的包容性。如NVRAM,看门狗,DS1286等实时时钟,字符LCD,AMD 768随机数发生器。

miscdevice共享一个主设备号MISC_MAJOR(10),但此设备号不同,所有的miscdevice设备形成一个链表,对设备访问时内核根据次设备号查找对应的 miscdevice设备,然后调用其中的file_operations结构体中注册的文件操作接口进程操作。


2:为什么要有misc驱动模型

第一,节省主设备号:
使用普通字符设备,不管该驱动的主设备号是静态还是动态分配,都会消耗一个主设备号,这太浪费了。而且如果你的这个驱动最终会提交到内核主线版本上的话,需要申请一个专门的主设备号,这也麻烦。
如果使用misc驱动的话就好多了。因为内核中已经为misc驱动分配了一个主设备号。当系统中拥有多个misc设备驱动时,那么它们的主设备号相同,而用子设备号来区分它们。

第二,使用简单:
有时候驱动开发人员需要开发一个功能较简单的字符设备驱动,导出接口让用户空间程序方便地控制硬件,只需要使用misc子系统提供的接口即可快速地创建一个misc设备驱动。
当使用普通的字符设备驱动时,如果开发人员需要导出操作接口给用户空间的话,需要自己去注册字符驱动,并创建字符设备class以自动在/dev下生成设备节点,相对麻烦一点。而misc驱动则无需考虑这些,基本上只需要把一些基本信息通过struct miscdevice交给misc_register()去处理即可。

本质上misc驱动也是一个字符设备驱动,可能相对特殊一点而已。在drivers/char/misc.c的misc驱动初始化函数misc_init()中实际上使用了MISC_MAJOR(主设备号为10)并调用register_chrdev()去注册了一个字符设备驱动。同时也创建了一个misc_class,使得最后可自动在/dev下自动生成一个主设备号为10的字符设备。总的来讲,如果使用misc驱动可以满足要求的话,那么这可以为开发人员剩下不少麻烦。

所以说misc驱动模型让我们很简单的在底层实现了字符设备驱动,并且在在应用层给予了一定的接口,节省了主设备号;其实就相当于一个杂货铺,乱七八糟的字符设备驱动模型都可以往里面堆。


3:驱动模型代码实现:
misc驱动的实现代码在driver/char/misc.c目录下,

misc_init函数:


 1 static int __init misc_init(void)

 2 {

 3     int err;

 4 

 5 #ifdef CONFIG_PROC_FS

 6     proc_create('misc', 0, NULL, &misc_proc_fops);

 7 #endif

 8     misc_class = class_create(THIS_MODULE, 'misc');

 9     err = PTR_ERR(misc_class);

10     if (IS_ERR(misc_class))

11         goto fail_remove;

12 

13     err = -EIO;

14     if (register_chrdev(MISC_MAJOR,'misc',&misc_fops))

15         goto fail_printk;

16     misc_class->devnode = misc_devnode;

17     return 0;

18 

19 fail_printk:

20     printk('unable to get major %d for misc devicesn', MISC_MAJOR);

21     class_destroy(misc_class);

22 fail_remove:

23     remove_proc_entry('misc', NULL);

24     return err;

25 }

26 subsys_initcall(misc_init);


misc_init


  class_create 创建了一个名为misc的类


  register_chrdev(MISC_MAJOR,'misc',&misc_fops)  使用register_chrdev注册了一个字符设备驱动,主设备号为MISC_MAJOR(10);


1 static const struct file_operations misc_fops = {

2     .owner        = THIS_MODULE,

3     .open        = misc_open,

4 };

misc类型驱动提供了一个统一.open函数misc_open函数;


misc_open 这个函数的实质是通过inode找到misc类的次设备号minor,然后在通过次设备号和misc链表的次设备号进行匹配,匹配好以后取出


 1 static int misc_open(struct inode * inode, struct file * file)

 2 {

 3     int minor = iminor(inode);

 4     struct miscdevice *c;

 5     int err = -ENODEV;

 6     const struct file_operations *old_fops, *new_fops = NULL;

 7 

 8     mutex_lock(&misc_mtx);

 9     

10     list_for_each_entry(c, &misc_list, list) {

11         if (c->minor == minor) {

12             new_fops = fops_get(c->fops);        

13             break;

14         }

15     }

16         

17     if (!new_fops) {

18         mutex_unlock(&misc_mtx);

19         request_module('char-major-%d-%d', MISC_MAJOR, minor);

20         mutex_lock(&misc_mtx);

21 

22         list_for_each_entry(c, &misc_list, list) {

23             if (c->minor == minor) {

24                 new_fops = fops_get(c->fops);

25                 break;

26             }

27         }

28         if (!new_fops)

29             goto fail;

30     }

31 

32     err = 0;

33     old_fops = file->f_op;

34     file->f_op = new_fops;

35     if (file->f_op->open) {

36         file->private_data = c;

37         err=file->f_op->open(inode,file);

38         if (err) {

39             fops_put(file->f_op);

40             file->f_op = fops_get(old_fops);

41         }

42     }

43     fops_put(old_fops);

44 fail:

45     mutex_unlock(&misc_mtx);

46     return err;

47 }


 1 int misc_register(struct miscdevice * misc)

 2 {

 3     struct miscdevice *c;

 4     dev_t dev;

 5     int err = 0;

 6 

 7     INIT_LIST_HEAD(&misc->list);

 8 

 9     mutex_lock(&misc_mtx);

10     list_for_each_entry(c, &misc_list, list) {

11         if (c->minor == misc->minor) {

12             mutex_unlock(&misc_mtx);

13             return -EBUSY;

14         }

15     }

16 

17     if (misc->minor == MISC_DYNAMIC_MINOR) {

18         int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);

19         if (i >= DYNAMIC_MINORS) {

20             mutex_unlock(&misc_mtx);

21             return -EBUSY;

22         }

23         misc->minor = DYNAMIC_MINORS - i - 1;

24         set_bit(i, misc_minors);

25     }

26 

27     dev = MKDEV(MISC_MAJOR, misc->minor);

28 

29     misc->this_device = device_create(misc_class, misc->parent, dev,

30                       misc, '%s', misc->name);

31     if (IS_ERR(misc->this_device)) {

32         int i = DYNAMIC_MINORS - misc->minor - 1;

33         if (i < DYNAMIC_MINORS && i >= 0)

34             clear_bit(i, misc_minors);

35         err = PTR_ERR(misc->this_device);

36         goto out;

37     }

38 

39     /*

40      * Add it to the front, so that later devices can 'override'

41      * earlier defaults

42      */

43     list_add(&misc->list, &misc_list);

44  out:

45     mutex_unlock(&misc_mtx);

46     return err;

47 }


在include/linux/miscdevice.h中定义了miscdevice  结构体,所有的misc模型驱动设备;都在内核围护的一个misc_list链表中;


内核维护一个misc_list链表,misc设备在misc_register注册的时候链接到这个链表,在misc_deregister中解除链接。


 1 struct miscdevice  {

 2     int minor;          //次设备号,若为 MISC_DYNAMIC_MINOR 自动分配 

 3     const char *name;      //设备名  

 4     const struct file_operations *fops;    //设备文件操作结构体

 5     struct list_head list;            //misc_list链表头  

 6     struct device *parent;

 7     struct device *this_device;

 8     const char *nodename;

 9     mode_t mode;

10 };


misc_register函数


 1 int misc_register(struct miscdevice * misc)

 2 {

 3     struct miscdevice *c;

 4     dev_t dev;

 5     int err = 0;

 6 

 7     INIT_LIST_HEAD(&misc->list);

 8 

 9     mutex_lock(&misc_mtx);

10     list_for_each_entry(c, &misc_list, list) {

11         if (c->minor == misc->minor) {

12             mutex_unlock(&misc_mtx);

13             return -EBUSY;

14         }

15     }

16 

17     if (misc->minor == MISC_DYNAMIC_MINOR) {

18         int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);

19         if (i >= DYNAMIC_MINORS) {

20             mutex_unlock(&misc_mtx);

21             return -EBUSY;

22         }

23         misc->minor = DYNAMIC_MINORS - i - 1;

24         set_bit(i, misc_minors);

25     }

26 

27     dev = MKDEV(MISC_MAJOR, misc->minor);

28 

29     misc->this_device = device_create(misc_class, misc->parent, dev,

30                       misc, '%s', misc->name);

31     if (IS_ERR(misc->this_device)) {

[1] [2]
关键字:linux  驱动开发  misc 引用地址:linux驱动开发(十)——misc杂散设备

上一篇:从samsung提供内核进行移植
下一篇:linux驱动开发之九鼎板载蜂鸣器驱动测试

推荐阅读最新更新时间:2026-03-21 10:53

linux驱动开发(十)——misc杂散设备
1:什么是misc驱动模型? 2:为什么要有misc驱动模型? 3:misc驱动模型的代码实现 4:misc驱动模型实战 参考: http://blog.csdn.net/yicao821/article/details/6785738 http://www.thinksaas.cn/topics/0/507/507168.html http://www.cnblogs.com/fellow1988/p/6235080.html https://www.zhihu.com/question/21508904 http://www.cnblogs.com/snake-hand/p/3212483.html http://blog.c
[单片机]
2416开发记录七: platform驱动之LED(misc
platform驱动的简单介绍 前几篇介绍了最简单的LED驱动写法,在linux2.6中提出了platform驱动,具体为什么要这么做后面博客再解释吧。 这里的platform驱动只是一个框架,并没有体现platform驱动的意义,因为在driver中没有使用device定义的资源。后面会再写一个真正的platfom。本篇算是入门练手,体会下吧。 pltform机制本身使用并不复杂,由两部分组成:platform_device和platform_driver。通过platform机制开发底层驱动的大致流程为:定义platform_deive- 注册platform_device- 定义platform_driver-
[单片机]
linux下的misc设备led示例
1.开发环境 Cpuinfo: Processor : ARMv7 Processor rev 2 (v7l) BogoMIPS : 998.15 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 CPU implementer : 0x41 CPU architecture : 7 CPU variant : 0x2 CPU part : 0xc08 CPU revision : 2 Hardware : SMDKV210 Bordinfo:
[单片机]
<font color='red'>linux</font>下的<font color='red'>misc</font><font color='red'>设备</font>led示例
IMX6ULL开发Linux_WIFI驱动实验
1.在迅为i.MX6ULL开发板上使用的是 usb 接口的 RTL8723 wifi 模块,原理图如下所示: 可以看到 RTL8723 模块的接口非常简单,只有 DP1 和 DM1 连接到 usb HUB 芯片上,就可以完成通信电路。 RTL8723 是 realtek 公司的 wifi 芯片,已经提供了 wifi 驱动源码,就不需要我们自己去编写了,只需要将提 供的 wifi 驱动源码添加到 Linux 内核中进行编译就可以了。 1.1在Linux内核中添加wifi驱动 首先获取 wifi 驱动源码,放到 Linux 内核 drivers/net/wireless 目录下,如下所示: rtl8723BU 目录下内容如下所示:
[单片机]
IMX6ULL<font color='red'>开发</font>板<font color='red'>Linux</font>_WIFI<font color='red'>驱动</font>实验
linux驱动开发之九鼎板载蜂鸣器驱动测试
字符设备驱动用的fileopretion结构体。 1、板载蜂鸣器的驱动测试 我手里有一个BSP,九鼎的Bsp,里面有蜂鸣器的驱动,我们先测试一下好不好用。我们拿到一个BSP时,如果要做或移植蜂鸣器的驱动,首先要确定下这个内核中究竟有没有蜂鸣器的驱动,我们可以用sourceInsight将内核放进去,搜索buzzer这个文件,看有没有,如果不行,也可以在内核中输入make menuconfig,利用这个配置界面来搜索buzzer英文,看不能找到相应的信息,从而也会知道这个设备在哪个路径下,通过对九鼎的内核进行make menuconfig后,搜索buzzer后,知道buzzer的驱动在/driver/char/buzzer/目录
[单片机]
手把手教你写Linux设备驱动---中断(三)--workqueue实现(基于友善之臂4412开发板)
上节,我们讲到如何来实现tasklet小任务机制 http://blog.csdn.NET/morixinguan/article/details/69666935 这节,我们来实现一下中断下半部的工作队列: 在写这个demo之前,我们要了解一下工作队列的相关数据结构还有API。 需要包含的头文件: #include Linux/workqueue.h 基本的数据结构: //工作队列结构 struct work_struct { atomic_long_t data; //链表处理 struct list_head entry; //工作处理函数 work_func_t
[单片机]
手把手教你写<font color='red'>Linux</font><font color='red'>设备</font><font color='red'>驱动</font>---中断(三)--workqueue实现(基于友善之臂4412<font color='red'>开发</font>板)
Linux设备驱动开发 - 字符设备驱动
struct cdev结构体: 1 struct cdev { 2 struct kobject kobj; /* 内嵌的kobject对象 */ 3 struct module *owner; /* 所属模块 */ 4 const struct file_operations *ops; /* 文件操作结构体 */ 5 struct list_head list; 6 dev_t dev; /* 设备号 */ 7 unsigned int count; 8 }; struct file_operations原形: 1 struct file_operations { 2 struct mod
[单片机]
<font color='red'>Linux</font><font color='red'>设备</font><font color='red'>驱动</font><font color='red'>开发</font> - 字符<font color='red'>设备</font><font color='red'>驱动</font>
linux-2.6.32在mini2440开发板上移植-移植UDA1341 音频驱动
1 在初始化文件中加入UDA1341 设备结构 Linux-2.6.32.2 已经完美的支持UDA1341 音频芯片的驱动, 我们只要在arch/arm/mach-s3c2440/mach-mini2440.c 文件中注册UDA1341 平台设备的控制端口就可以了,打开mach-mini2440.c,添加如下内容: ;在文件首部添加头文件 #include sound/s3c24xx_uda134x.h ;在LCD 平台设备后面添加UDA1341 设备结构 static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data = { .l3_clk =
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved