杂项设备MISC

杂项设备共用主设备号10,MISC就是最简单的字符设备驱动。
misc 驱动通常嵌套在platform 总线驱动中,实现复杂的驱动。
所有的MISC设备驱动的主设备号都是10,不同的设备使用不同的次设备号。
MISC驱动的核心就是初始化struct miscdevice 结构体。

struct miscdevice
{int minor; /* 子设备号 需要用户填写*/const char *name; /* 设备名字 需要用户填写*/const struct file_operations *fops; /* 设备操作集 需要用户填写*/struct list_head list;struct device *parent;struct device *this_device;const struct attribute_group **groups;const char *nodename;umode_t mode;
};

定义一个misc 设备,我们需要设置minor,name,fops 这三个成员变量,minor是次设备号,有几个次设备号被系统占用了,定义在include/linux/miscdevice.h

#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2 /* unused */
#define ATIXL_BUSMOUSE_MINOR 3 /* unused */
/*#define AMIGAMOUSE_MINOR 4 FIXME OBSOLETE */
#define ATARIMOUSE_MINOR 5 /* unused */
#define SUN_MOUSE_MINOR 6 /* unused */
......
#define MISC_DYNAMIC_MINOR 255

若指定次设备号为255 表示由内核自动分配次设备号。
设置好miscdevice 结构体后,就可以使用misc_register 函数向系统注册一个MISC设备。
替代普通字符驱动注册,如下步骤:

alloc_chrdev_region()    //申请设备号
cdev_init()             //初始化cdev
cdev_add()              //添加 cdev
class_create()          //创建 类
device_create()         //创建 设备

使用杂项misc设备,只需要调用misc_register 函数就可以完成 alloc_chrdev_region,cdev_init,cdev_add,class_create,device_create 这些函数完成的功能。
卸载杂项字符设备时,需要调用misc_deregister 函数来注销misc 设备。
替代普通字符设备的卸载操作,如下:

cdev_del()                   //删除设备
unregister_chrdev_region()  //注销设备号
device_destroy()            //删除设备
class_destroy()             //删除类

分析/drivers/char/msic.c
subsys_initcall(misc_init); //会在系统初始化是调用到

misc_int()

static int __init misc_init(void)
{int err;
#ifdef CONFIG_PROC_FSproc_create("misc", 0, NULL, &misc_proc_fops);
#endifmisc_class = class_create(THIS_MODULE, "misc");  //创建msic_class类err = PTR_ERR(misc_class);if (IS_ERR(misc_class))goto fail_remove;err = -EIO;if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) //申请主设备号10的256个设备号,cdev_addgoto fail_printk;misc_class->devnode = misc_devnode;return 0;
fail_printk:printk("unable to get major %d for misc devices\n", MISC_MAJOR);class_destroy(misc_class);
fail_remove:remove_proc_entry("misc", NULL);return err;
}

misc_register()

misc_deregister()

注册misc设备

int misc_register(struct miscdevice * misc)
{struct miscdevice *c;dev_t dev;int err = 0;INIT_LIST_HEAD(&misc->list);//初始化list节点,用来添加到misc_list中的mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) { //检查minor是否已分配if (c->minor == misc->minor) {mutex_unlock(&misc_mtx);return -EBUSY;}}if (misc->minor == MISC_DYNAMIC_MINOR) { //misc自动分配次设备号int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);if (i >= DYNAMIC_MINORS) {mutex_unlock(&misc_mtx);return -EBUSY;}misc->minor = DYNAMIC_MINORS - i - 1;set_bit(i, misc_minors); //设置映射表}dev = MKDEV(MISC_MAJOR, misc->minor);//设备号misc->this_device = device_create(misc_class, misc->parent, dev,misc, "%s", misc->name);//创建设备节点if (IS_ERR(misc->this_device)) {int i = DYNAMIC_MINORS - misc->minor - 1;if (i < DYNAMIC_MINORS && i >= 0)clear_bit(i, misc_minors);err = PTR_ERR(misc->this_device);goto out;}/* Add it to the front, so that later devices can "override"* earlier defaults */list_add(&misc->list, &misc_list); //添加到misc_list头部,为了新的可以覆盖旧的设备out:mutex_unlock(&misc_mtx);return err;
}int misc_deregister(struct miscdevice *misc)
{int i = DYNAMIC_MINORS - misc->minor - 1;if (WARN_ON(list_empty(&misc->list)))return -EINVAL;mutex_lock(&misc_mtx);list_del(&misc->list);//删除节点device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));//销毁设备节点if (i < DYNAMIC_MINORS && i >= 0)clear_bit(i, misc_minors);mutex_unlock(&misc_mtx);return 0;
}

misc_open()

static int misc_open(struct inode * inode, struct file * file)
{int minor = iminor(inode); //获取次设备号struct miscdevice *c;int err = -ENODEV;const struct file_operations *old_fops, *new_fops = NULL;mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) { //遍历misc_list,找到miscdevice->fopsif (c->minor == minor) {new_fops = fops_get(c->fops);        break;}}    if (!new_fops) {mutex_unlock(&misc_mtx);request_module("char-major-%d-%d", MISC_MAJOR, minor);//mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) {if (c->minor == minor) {new_fops = fops_get(c->fops);break;}}if (!new_fops)goto fail;}err = 0;old_fops = file->f_op;file->f_op = new_fops;      //替换file->f_opsif (file->f_op->open) {file->private_data = c;err=file->f_op->open(inode,file);if (err) {fops_put(file->f_op);file->f_op = fops_get(old_fops);}}fops_put(old_fops);
fail:mutex_unlock(&misc_mtx);return err;
}

driver()

 struct miscdevice miscLeds;miscLeds.fops = &misc_leds_ops;miscLeds.name = "misc3Leds";miscLeds.minor = MISC_DYNAMIC_MINOR;ret = misc_register(&miscLeds);

MISC device相关推荐

  1. rm: cannot remove directory `misc': Device or resource busy

    rm: cannot remove directory `misc': Device or resource busy 解决方法: [root@crmnormal misc]# cat /etc/mi ...

  2. linux misc device字符杂项设备驱动

    杂项设备也是在嵌入式系统中用得比较多的一种设备驱动.miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同.misc设备其实就是特殊的字符设备,主设备编号采用10,并且可自 ...

  3. backlight misc驱动范例 及应用程序范例

    1.编写背光驱动.文件名为my2440_backlight.c (1) #include <linux/errno.h> #include <linux/kernel.h> # ...

  4. Linux MISC 驱动实验

    目录 MISC 设备驱动简介 硬件原理图分析 实验程序编写 修改设备树 beep 驱动程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 misc 的意思是混合.杂项的,因此MIS ...

  5. misc类设备与蜂鸣器驱动

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 一.板载蜂鸣器驱动测试 1.驱动部分 (1)九鼎移植内核已经提供了蜂鸣器驱动源码,但如何查找是否已经有驱动文件? 法一 ...

  6. MISC机制编写字符驱动程序

    一.杂项设备 在上次的实验中编写了一个内核模块,是使用内核提供的API实现了一个简单的虚拟设备的驱动,其中字符设备是使用函数alloc_chrdev_region -> cdev_alloc-& ...

  7. 韦东山 IMX6ULL和正点原子_正点原子Linux第五十七章Linux MISC驱动实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第五十七章Linux MISC驱动实验 misc的意思是 ...

  8. Linux内核的misc框架

    Linux内核为每种设备都抽象出了框架,开发人员只需往框架中填充信息即可进行设备的注册.下面来讲解一下Linux内核的misc框架. misc又叫杂散类设备,在早期的内核中,向ADC.WATCHDOG ...

  9. Linux Miscellaneous Device

    参考原文:http://www.tldp.org/HOWTO/text/Module-HOWTO 15.7. Miscellaneous Device Driver15.7.1. misc: devi ...

最新文章

  1. 爬虫之数据提取响应内容的分类
  2. MDEV Primer
  3. cmake构建器最新Windows/MACOS/LINUX版本分享
  4. 嵌入式Linux系统中的.lds链接脚本基础
  5. 数据库-优化-数据库系统配置优化-配置文件优化
  6. android 成长日记 8.Fragment学习之方法回调
  7. [REGEX] 匹配任意字符(包括换行符)
  8. 达摩院送你100万,请坚持“看月亮”
  9. java569_java如何实现这样一个程序
  10. 13muduo_base库源码分析(四)
  11. Eclipse 常用快捷键和使用技巧
  12. 公众号内打开提示404_微信公众号文章内如何插入视频?
  13. 关于VLAN Tag,PVID的问题
  14. 无线串口服务器规模,无线串口服务器讲述.doc
  15. Linux虚拟机克隆后网络冲突解决办法
  16. 京东商品的历史价格走势
  17. 关于 移动端隐藏scroll滚动条::-webkit-scrollbar
  18. 我参加第七届NVIDIA Sky Hackathon——训练CV模型
  19. 基于加密短信验证码的蓝牙智能锁设计
  20. java vbs_一键定位配置JAVA SDK 环境变量 VBS脚本全自动操作正式开源

热门文章

  1. 费用报销java_ERP费用报销操作与设计--开源软件诞生31
  2. nodejs 爬取动态网页
  3. 云安全:云计算的安全风险、模型和策略
  4. Parallels Desktop窗口模式更改方法
  5. Exchange邮件pst数据的导出与查看
  6. Array.sort用法
  7. 软件20-4 杜明童 laravel
  8. iClient for OpenLayer结合Mapv制作支援迁移路线
  9. java 单链表数据结构的示例
  10. 实验七—高级数据管理(一)