zoukankan      html  css  js  c++  java
  • Linux下GPIO驱动(五) misc_register();

    //

    struct miscdevice  {
        int minor;
        const char *name;
        const struct file_operations *fops;
        struct list_head list;
        struct device *parent;
        struct device *this_device;
        const char *nodename;
        mode_t mode;
    };
    
     int misc_register(struct miscdevice * misc);//注册为杂项设备
     int misc_deregister(struct miscdevice *misc);//注销

    miscdevice的数据结构如下图所示:

    int misc_register(struct miscdevice * misc)
    {
        struct miscdevice *c;
        dev_t dev;
        int err = 0;
    
        INIT_LIST_HEAD(&misc->list);// // 初始化链表头,将misc->list的next和pre都指向自己
    
        mutex_lock(&misc_mtx);// 获取互斥锁, or睡眠
        list_for_each_entry(c, &misc_list, list) { // 遍历整个misc_list链表,所有的杂项驱动设备都有一个miscdevice数据结构,这些杂项驱动设备通过一个全局的misc_list链表连在一起, 相当一个记录
            if (c->minor == misc->minor) {// 如果misc_list中已经有了这个设备(minor相同),则解锁返回,这里c是遍历时的tmp miscdevice,指向当前遍历节点
                mutex_unlock(&misc_mtx);
                return -EBUSY;
            }
        }
    
        if (misc->minor == MISC_DYNAMIC_MINOR) { // 如果misc_list中没有该设备,判断minor是否准备动态分配,实验中如此设置
            int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);// misc_minors是杂项设备位图,总共有64个位DYNAMIC_MINORS=64,表示可以注册64个杂项设备,这句代码找到位图中的空闲位置(表示还能加新设备)
            if (i >= DYNAMIC_MINORS) {// 如果超过总设备数,则解锁返回
                mutex_unlock(&misc_mtx);
                return -EBUSY;
            }
            misc->minor = DYNAMIC_MINORS - i - 1;// 计算子设备号,赋值到misc->minor
            
            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);// 在sysfs中创建并注册一个设备,可以在/dev下面看到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;
    }
    /**
     *    misc_deregister - unregister a miscellaneous device
     *    @misc: device to unregister
     *
     *    Unregister a miscellaneous device that was previously
     *    successfully registered with misc_register(). Success
     *    is indicated by a zero return, a negative errno code
     *    indicates an error.
     */
    
    int misc_deregister(struct miscdevice *misc)
    {
        int i = DYNAMIC_MINORS - misc->minor - 1;
    
        if (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;
    }
    在Linux初始化期间会执行misc_init();
    static
    int __init misc_init(void) { int err; #ifdef CONFIG_PROC_FS //在proc文件系统下创建一个"misc"目录。 misc_proc_fops是该文件系统下文件的操作函数集 proc_create("misc", 0, NULL, &misc_proc_fops); #endif misc_class = class_create(THIS_MODULE, "misc"); // 前面device_create()中的misc_class就是在这里初始化的 err = PTR_ERR(misc_class); if (IS_ERR(misc_class)) goto fail_remove; err = -EIO; if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))//注册一个主设备号为MISC_MAJOR(10)的字符设备,设备操作函数集为misc_fops goto 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; }
  • 相关阅读:
    简单理解Vue中的nextTick
    vue-router路由元信息及keep-alive组件级缓存
    Webpack配置区分开发环境和生产环境
    理解Vue.mixin,利用Vue.mixin正确的偷懒
    HTML5实现首页动态视频背景
    vue-router钩子函数实现路由守卫
    Vue路由(vue-router)详细讲解指南
    一文轻松搞懂Vuex
    利用HBuilder打包Vue开发的webapp为app
    WPF中剪贴板操作Clipboard
  • 原文地址:https://www.cnblogs.com/hello2mhb/p/3279425.html
Copyright © 2011-2022 走看看