sysfs与kobject交互

来源:互联网 发布:高中数学矩阵与变换 编辑:程序博客网 时间:2024/06/05 14:48

对于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结构中。

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

[cpp] view plaincopy
  1. struct attribute {  
  2.     const char        *name;        //属性名字,在kobject的sysfs目录中显示.  
  3.     struct module        *owner;    //指向模块的指针,该模块负责实现这些属性。  
  4.     mode_t            mode;         //用作属性的保护位。  
  5. #ifdef CONFIG_DEBUG_LOCK_ALLOC  
  6.     struct lock_class_key    *key;  
  7.     struct lock_class_key    skey;  
  8. #endif  
  9. };  

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

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

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

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

三、非默认属性

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

[cpp] view plaincopy
  1. /** 
  2.  *    sysfs_create_file - create an attribute file for an object. 
  3.  *    @kobj:    object we're creating for. 
  4.  *    @attr:    attribute descriptor. 
  5.  */  
  6. int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)  
  7. {  
  8.     BUG_ON(!kobj || !kobj->sd || !attr);  
  9.     return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);  
  10. }  
  11. int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)  
  12. {  
  13.     int err = 0;  
  14.     int i;  
  15.     for (i = 0; ptr[i] && !err; i++)  
  16.         err = sysfs_create_file(kobj, ptr[i]);  
  17.     if (err)  
  18.         while (--i >= 0)  
  19.             sysfs_remove_file(kobj, ptr[i]);  
  20.     return err;  
  21. }  

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

[cpp] view plaincopy
  1. /** 
  2.  *    sysfs_remove_file - remove an object attribute. 
  3.  *    @kobj:    object we're acting for. 
  4.  *    @attr:    attribute descriptor. 
  5.  * 
  6.  *    Hash the attribute name and kill the victim. 
  7.  */  
  8. void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)  
  9. {  
  10.     sysfs_hash_and_remove(kobj->sd, NULL, attr->name);  
  11. }  
  12. void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)  
  13. {  
  14.     int i;  
  15.     for (i = 0; ptr[i]; i++)  
  16.         sysfs_remove_file(kobj, ptr[i]);  
  17. }  

四、二进制属性

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

bin_attribute结构定义如下:

[cpp] view plaincopy
  1. struct bin_attribute {  
  2.     struct attribute    attr;   //定义了名字,所有者,二进制属性的权限  
  3.     size_t            size;     //制定了二进制属性的最大长度。  
  4.     void            *private;  
  5.     ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,  //加载过程中调用read/write函数  
  6.             char *, loff_t, size_t);  
  7.     ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *,  
  8.              char *, loff_t, size_t);  
  9.     int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,  
  10.          struct vm_area_struct *vma);  
  11. };  

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

[cpp] view plaincopy
  1. /** 
  2.  *    sysfs_create_bin_file - create binary file for object. 
  3.  *    @kobj:    object. 
  4.  *    @attr:    attribute descriptor. 
  5.  */  
  6. int sysfs_create_bin_file(struct kobject *kobj,  
  7.              const struct bin_attribute *attr)  
  8. {  
  9.     BUG_ON(!kobj || !kobj->sd || !attr);  
  10.     return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);  
  11. }  
  12. /** 
  13.  *    sysfs_remove_bin_file - remove binary file for object. 
  14.  *    @kobj:    object. 
  15.  *    @attr:    attribute descriptor. 
  16.  */  
  17. void sysfs_remove_bin_file(struct kobject *kobj,  
  18.              const struct bin_attribute *attr)  
  19. {  
  20.     sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);  
  21. }  


五、符号链接

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

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

[cpp] view plaincopy
  1. /** 
  2.  *    sysfs_create_link - create symlink between two objects. 
  3.  *    @kobj:    object whose directory we're creating the link in. 
  4.  *    @target:    object we're pointing to. 
  5.  *    @name:        name of the symlink. 
  6.  */  
  7. int sysfs_create_link(struct kobject *kobj, struct kobject *target,  
  8.          const char *name)  
  9. {  
  10.     return sysfs_do_create_link(kobj, target, name, 1);  
  11. }  
  12.   
  13. /** 
  14.  *    sysfs_delete_link - remove symlink in object's directory. 
  15.  *    @kobj:    object we're acting for. 
  16.  *    @targ:    object we're pointing to. 
  17.  *    @name:    name of the symlink to remove. 
  18.  * 
  19.  *    Unlike sysfs_remove_link sysfs_delete_link has enough information 
  20.  *    to successfully delete symlinks in tagged directories. 
  21.  */  
  22. void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,  
  23.             const char *name)  
  24. {  
  25.     const void *ns = NULL;  
  26.     spin_lock(&sysfs_assoc_lock);  
  27.     if (targ->sd && sysfs_ns_type(kobj->sd))  
  28.         ns = targ->sd->s_ns;  
  29.     spin_unlock(&sysfs_assoc_lock);  
  30.     sysfs_hash_and_remove(kobj->sd, ns, name);  
  31. }  
  32. /** 
  33.  *    sysfs_remove_link - remove symlink in object's directory. 
  34.  *    @kobj:    object we're acting for. 
  35.  *    @name:    name of the symlink to remove. 
  36.  */  
  37. void sysfs_remove_link(struct kobject * kobj, const char * name)  
  38. {  
  39.     struct sysfs_dirent *parent_sd = NULL;  
  40.     if (!kobj)  
  41.         parent_sd = &sysfs_root;  
  42.     else  
  43.         parent_sd = kobj->sd;  
  44.     sysfs_hash_and_remove(parent_sd, NULL, name);  
  45. }