Class 类

类是一个设备的高层概念,它抽象出了低层的实现细节。

所有的类都显示在sys/class/目录下。

如:
所有的网络接口都集中在/sys/class/net/下,输入设备都集中在/sys/class/input/下, 串行设备都集中在sys/class/tty/下。

在许多情况下,类子系统是向用户空间导出信息的最好方法。

1. class 定义在device.h中

    /*
     * device classes
     */
    struct class {
        const char        *name;    //每个类都需要一个唯一的名字,他将显示在sys/class/中
        struct module        *owner;
        struct class_attribute        *class_attrs;  //一个类注册后,将创建clas_attrs指向的数组中的所有属性
        struct device_attribute        *dev_attrs;
        struct kobject            *dev_kobj;
        int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
        char *(*devnode)(struct device *dev, mode_t *mode);
        void (*class_release)(struct class *class);
        void (*dev_release)(struct device *dev);
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
        const struct kobj_ns_type_operations *ns_type;
        const void *(*namespace)(struct device *dev);
        const struct dev_pm_ops *pm;
        struct class_private *p;
    };

class_attribute

    struct class_attribute {
     struct attribute attr;
     ssize_t (*show)(struct class *class, struct class_attribute *attr,
       char *buf);
     ssize_t (*store)(struct class *class, struct class_attribute *attr,
       const char *buf, size_t count);
    };

2. 类注册与注销: class_register()/class_unregister()

    /* This is a #define to keep the compiler from merging different
     * instances of the __key variable */
    #define class_register(class)            \
    ({                        \
        static struct lock_class_key __key;    \
        __class_register(class, &__key);    \
    })

 

    int __class_register(struct class *cls, struct lock_class_key *key)
    {
        struct class_private *cp;
        int error;
        pr_debug("device class '%s': registering\n", cls->name);
        cp = kzalloc(sizeof(*cp), GFP_KERNEL);
        if (!cp)
            return -ENOMEM;
        klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put);
        INIT_LIST_HEAD(&cp->class_interfaces);
        kset_init(&cp->class_dirs);
        __mutex_init(&cp->class_mutex, "struct class mutex", key);
        error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
        if (error) {
            kfree(cp);
            return error;
        }
        /* set the default /sys/dev directory for devices of this class */
        if (!cls->dev_kobj)
            cls->dev_kobj = sysfs_dev_char_kobj;
    #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
        /* let the block class directory show up in the root of sysfs */
        if (cls != &block_class)
            cp->class_subsys.kobj.kset = class_kset;
    #else
        cp->class_subsys.kobj.kset = class_kset;
    #endif
        cp->class_subsys.kobj.ktype = &class_ktype;
        cp->class = cls;
        cls->p = cp;
        error = kset_register(&cp->class_subsys);
        if (error) {
            kfree(cp);
            return error;
        }
        error = add_class_attrs(class_get(cls));
        class_put(cls);
        return error;
    }
    EXPORT_SYMBOL_GPL(__class_register);

    void class_unregister(struct class *cls)
    {
        pr_debug("device class '%s': unregistering\n", cls->name);
        remove_class_attrs(cls);
        kset_unregister(&cls->p->class_subsys);
    }

3. 处理属性接口:

    int class_create_file(struct class *cls, const struct class_attribute *attr)
    {
        int error;
        if (cls)
            error = sysfs_create_file(&cls->p->class_subsys.kobj,
                         &attr->attr);
        else
            error = -EINVAL;
        return error;
    }
    void class_remove_file(struct class *cls, const struct class_attribute *attr)
    {
        if (cls)
            sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr);
    }

4. 类接口,class_interface

    struct class_interface {
        struct list_head    node;
        struct class        *class;
        int (*add_dev)        (struct device *, struct class_interface *);
        void (*remove_dev)    (struct device *, struct class_interface *);
    };

类接口的注册与注销:

    int class_interface_register(struct class_interface *class_intf)
    {
        struct class *parent;
        struct class_dev_iter iter;
        struct device *dev;
        if (!class_intf || !class_intf->class)
            return -ENODEV;
        parent = class_get(class_intf->class);
        if (!parent)
            return -EINVAL;
        mutex_lock(&parent->p->class_mutex);
        list_add_tail(&class_intf->node, &parent->p->class_interfaces);
        if (class_intf->add_dev) {
            class_dev_iter_init(&iter, parent, NULL, NULL);
            while ((dev = class_dev_iter_next(&iter)))
                class_intf->add_dev(dev, class_intf);
            class_dev_iter_exit(&iter);
        }
        mutex_unlock(&parent->p->class_mutex);
        return 0;
    }
    void class_interface_unregister(struct class_interface *class_intf)
    {
        struct class *parent = class_intf->class;
        struct class_dev_iter iter;
        struct device *dev;
        if (!parent)
            return;
        mutex_lock(&parent->p->class_mutex);
        list_del_init(&class_intf->node);
        if (class_intf->remove_dev) {
            class_dev_iter_init(&iter, parent, NULL, NULL);
            while ((dev = class_dev_iter_next(&iter)))
                class_intf->remove_dev(dev, class_intf);
            class_dev_iter_exit(&iter);
        }
        mutex_unlock(&parent->p->class_mutex);
        class_put(parent);
    }


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值