linux设备驱动模型 - sys/kobject

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l289123557/article/details/68614079

1. sysfs

1.1 sysfs文件系统注册

在系统启动时会注册sysfs文件系统

(fs/sysfs/mount.c)

int __init sysfs_init(void)
{
    int err;

    sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
                    NULL);
    if (IS_ERR(sysfs_root))
        return PTR_ERR(sysfs_root);

    sysfs_root_kn = sysfs_root->kn;

    err = register_filesystem(&sysfs_fs_type);
    if (err) {
        kernfs_destroy_root(sysfs_root);
        return err;
    }

    return 0;
}

1.2 API

在/sys目录下创建目录和各种文件有一系列API,下面总结介绍一些:

(include/linux/sysfs.h)

1.2.1 目录相关

int  sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
void sysfs_remove_dir(struct kobject *kobj);
int  sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
                     const void *new_ns);
int  sysfs_move_dir_ns(struct kobject *kobj,
                   struct kobject *new_parent_kobj,
                   const void *new_ns);

1.2.2 mount

int __must_check sysfs_create_mount_point(struct kobject *parent_kobj,
                      const char *name);
void sysfs_remove_mount_point(struct kobject *parent_kobj,
                  const char *name);

1.2.3 file

int __must_check sysfs_create_file_ns(struct kobject *kobj,
                      const struct attribute *attr,
                      const void *ns);
int __must_check sysfs_create_files(struct kobject *kobj,
                   const struct attribute **attr);
int __must_check sysfs_chmod_file(struct kobject *kobj,
                  const struct attribute *attr, umode_t mode);
void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
              const void *ns);
bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
                   const char *name);
int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
                      struct kobject *target,
                      const char *name);
void sysfs_remove_link(struct kobject *kobj, const char *name);

int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target,
             const char *old_name, const char *new_name,
             const void *new_ns);

void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
            const char *name);

2. kobject

sysfs下的设备都是通过分层组织归类的,要把这些关系组织起来,就是通过kobject,kobject在sysfs下的表现形式就是一个目录,而文件是由attribute来表示,由sysfs下的API函数来创建(如:sysfs_create_file_ns)

2.1 kobject

对于sysfs下的每个目录都用kobject来抽象

struct kobject {
    const char      *name;-------------------------名字
    struct list_head    entry;
    struct kobject      *parent;-----------------------父kobject指针
    struct kset     *kset;-------------------------所属kset
    struct kobj_type    *ktype;------------------------用于属性操作接口
    struct kernfs_node  *sd; /* sysfs directory entry */--kernfs接口
    struct kref     kref;--------------------------引用计数
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
    struct delayed_work release;
#endif
    unsigned int state_initialized:1;
    unsigned int state_in_sysfs:1;
    unsigned int state_add_uevent_sent:1;
    unsigned int state_remove_uevent_sent:1;
    unsigned int uevent_suppress:1;
};

kobject的创建

extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype);

int kobject_add(struct kobject *kobj, struct kobject *parent,
        const char *fmt, ...);

int kobject_init_and_add(struct kobject *kobj,
             struct kobj_type *ktype, struct kobject *parent,
             const char *fmt, ...);

kobject的删除

extern void kobject_del(struct kobject *kobj);

2.2 kset

kset就是一系列同类型kobject的集合,就像一个目录下会包含多个目录,上级目录一般是个kset,kobject和kset的关系如图所示:

这里写图片描述

struct kset {
    struct list_head list;-------------------------链接所有kobject
    spinlock_t list_lock;
    struct kobject kobj;---------------------------嵌入的kobject
    const struct kset_uevent_ops *uevent_ops;------kset操作函数
};

kset的创建及注册

extern void kset_init(struct kset *kset);
extern int __must_check kset_register(struct kset *kset);

kset的删除

extern void kset_unregister(struct kset *kset);

2.3 kobj_type

一些kobject下会有一些属性,在/sys下的表现形式就是文件,通过这些文件可以向用户提供一些操作接口

struct kobj_type {
    void (*release)(struct kobject *kobj);------------释放kobject函数接口
    const struct sysfs_ops *sysfs_ops;----------------属性操作函数实现接口
    struct attribute **default_attrs;-----------------属性定义
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
};
struct attribute {
    const char      *name;----------------名字
    umode_t         mode;-----------------文件权限
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    bool            ignore_lockdep:1;
    struct lock_class_key   *key;
    struct lock_class_key   skey;
#endif
};

3. 系统初始化sys创建的一些默认目录

(drivers/base/core.c)

int __init devices_init(void)
{
    devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
    if (!devices_kset)-------------------创建/sys/devices目录
        return -ENOMEM;
    dev_kobj = kobject_create_and_add("dev", NULL);
    if (!dev_kobj)-----------------------创建/sys/dev目录
        goto dev_kobj_err;
    sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
    if (!sysfs_dev_block_kobj)-----------创建/sys/block目录
        goto block_kobj_err;
    sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
    if (!sysfs_dev_char_kobj)------------创建/sys/char目录
        goto char_kobj_err;

    return 0;

 char_kobj_err:
    kobject_put(sysfs_dev_block_kobj);
 block_kobj_err:
    kobject_put(dev_kobj);
 dev_kobj_err:
    kset_unregister(devices_kset);
    return -ENOMEM;
}

(drivers/base/bus.c)

int __init buses_init(void)
{
    bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
    if (!bus_kset)------------------创建/sys/bus,初始化全局变量bus_kset
        return -ENOMEM;

    system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
    if (!system_kset)---------------创建/sys/system,初始化全局变量system_kset
        return -ENOMEM;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/l289123557/article/details/68614079