sysfs与kobject交互

对于sysfs中的每个目录,内核中都会存在一个对应的kobject。

每个kobject都输出一个或多个属性,他们在kobject的sysfs目录中表现为文件,其内容由内核生成,这些内容揭示了kobject和sysfs在底层是如何交互的。

只要调用kobject_add(),就能在sysfs中显示kobject.

一、创建sysfs入口需要注意一下几点:

1.kobject在sysfs中的入口始终都是一个目录,因此调用kobject_add()将在sysfs中创建一个目录。通常这个目录包含一个或多个属性(attr)。

2,分配给kobject的名字就是sysfs中的目录名。该文件名不能包含反斜杠,并强烈建议不要使用空格。

3.sysfs入口在目录中的位置对应于kobject的parent指针。如果调用kobject_add()的时候,parent=null,那么它将被嵌入到新kobject的kset中的kobject,这样sysfs分层结构通常与kset创建的内部结构相匹配。

二、默认属性:

当创建kobject的时候,都会给每个kobject一系列默认属性。这些属性保存在kobj_type结构中。

    struct kobj_type {
        void (*release)(struct kobject *kobj);
        const struct sysfs_ops *sysfs_ops;  //提供了实现这些属性的方法。
        struct attribute **default_attrs;   //默认属性,保存了属性列表,用于创建该类型的每一个kobject。
        const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
        const void *(*namespace)(struct kobject *kobj);
    };
default_attrs指向一个包含attribute结构数组的指针:

    struct attribute {
        const char        *name;        //属性名字,在kobject的sysfs目录中显示.
        struct module        *owner;    //指向模块的指针,该模块负责实现这些属性。
        mode_t            mode;         //用作属性的保护位。
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lock_class_key    *key;
        struct lock_class_key    skey;
    #endif
    };

default_attrs链表中的最后一个元素必须用0填充。

default_attrs数组只是说明了都有哪些属性,但是并没有告诉sysfs如何真正实现这些属性,所以,这个任务就交给了kobj_type->sysfs_ops成员。这个结构定义在include/linux/sysfs.h中

    struct sysfs_ops {
        ssize_t    (*show)(struct kobject *, struct attribute *,char *);
        ssize_t    (*store)(struct kobject *,struct attribute *,const char *, size_t);
    };
a. 当用户控件读取一个属性时,内核会用指向kobject的指针和属性结构来调用show方法。

b. 当拥有对属性的写权限时,可以调用store函数。

三、非默认属性

如果希望在kobject的sysfs目录中添加新的属性,可以填写一个attribute结构,并把它传递给下面的函数:

    /**
     *    sysfs_create_file - create an attribute file for an object.
     *    @kobj:    object we're creating for.
     *    @attr:    attribute descriptor.
     */
    int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
    {
        BUG_ON(!kobj || !kobj->sd || !attr);
        return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
    }
    int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
    {
        int err = 0;
        int i;
        for (i = 0; ptr[i] && !err; i++)
            err = sysfs_create_file(kobj, ptr[i]);
        if (err)
            while (--i >= 0)
                sysfs_remove_file(kobj, ptr[i]);
        return err;
    }

调用下面的函数删除一个属性:

    /**
     *    sysfs_remove_file - remove an object attribute.
     *    @kobj:    object we're acting for.
     *    @attr:    attribute descriptor.
     *
     *    Hash the attribute name and kill the victim.
     */
    void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
    {
        sysfs_hash_and_remove(kobj->sd, NULL, attr->name);
    }
    void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
    {
        int i;
        for (i = 0; ptr[i]; i++)
            sysfs_remove_file(kobj, ptr[i]);
    }

四、二进制属性

如果系统中需要load firmware时,会使用二进制sysfs属性将firmware传递给内核。

bin_attribute结构定义如下:

    struct bin_attribute {
        struct attribute    attr;   //定义了名字,所有者,二进制属性的权限
        size_t            size;     //制定了二进制属性的最大长度。
        void            *private;
        ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,  //加载过程中调用read/write函数
                char *, loff_t, size_t);
        ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *,
                 char *, loff_t, size_t);
        int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
             struct vm_area_struct *vma);
    };

下面的调用创建和删除二进制属性:sysfs_create_bin_file()/sysfs_remove_bin_file().

    /**
     *    sysfs_create_bin_file - create binary file for object.
     *    @kobj:    object.
     *    @attr:    attribute descriptor.
     */
    int sysfs_create_bin_file(struct kobject *kobj,
                 const struct bin_attribute *attr)
    {
        BUG_ON(!kobj || !kobj->sd || !attr);
        return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
    }
    /**
     *    sysfs_remove_bin_file - remove binary file for object.
     *    @kobj:    object.
     *    @attr:    attribute descriptor.
     */
    void sysfs_remove_bin_file(struct kobject *kobj,
                 const struct bin_attribute *attr)
    {
        sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
    }


五、符号链接

sysfs文件系统具有树形结构,以反映kobject之间的组织层次关系。

这种关系可以通过建立符号链接实现:sysfs_create_link()/ sysfs_remove_link():

    /**
     *    sysfs_create_link - create symlink between two objects.
     *    @kobj:    object whose directory we're creating the link in.
     *    @target:    object we're pointing to.
     *    @name:        name of the symlink.
     */
    int sysfs_create_link(struct kobject *kobj, struct kobject *target,
             const char *name)
    {
        return sysfs_do_create_link(kobj, target, name, 1);
    }

    /**
     *    sysfs_delete_link - remove symlink in object's directory.
     *    @kobj:    object we're acting for.
     *    @targ:    object we're pointing to.
     *    @name:    name of the symlink to remove.
     *
     *    Unlike sysfs_remove_link sysfs_delete_link has enough information
     *    to successfully delete symlinks in tagged directories.
     */
    void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
                const char *name)
    {
        const void *ns = NULL;
        spin_lock(&sysfs_assoc_lock);
        if (targ->sd && sysfs_ns_type(kobj->sd))
            ns = targ->sd->s_ns;
        spin_unlock(&sysfs_assoc_lock);
        sysfs_hash_and_remove(kobj->sd, ns, name);
    }
    /**
     *    sysfs_remove_link - remove symlink in object's directory.
     *    @kobj:    object we're acting for.
     *    @name:    name of the symlink to remove.
     */
    void sysfs_remove_link(struct kobject * kobj, const char * name)
    {
        struct sysfs_dirent *parent_sd = NULL;
        if (!kobj)
            parent_sd = &sysfs_root;
        else
            parent_sd = kobj->sd;
        sysfs_hash_and_remove(parent_sd, NULL, name);
    }


 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值