1. 程式人生 > >linux裝置驅動模型 - sys/kobject

linux裝置驅動模型 - sys/kobject

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;
}