linux文件系统的系统分析--(六)sysfs下目录的创建

来源:互联网 发布:域名后缀org含义 编辑:程序博客网 时间:2024/04/24 01:26

 对sysfs和设备模型有了解的都会知道sysfs实际是为了将设备模型导出到用户空间的一个内存文件系统。

       设备模型的关键结构体kobject会组成设备模型的树形结构,而sysfs的关键结构体sysfs_dirent也是类似的树形的结构,vfs中的dentry同样是类似的树形结构。

       sysfs目录文件的创建都是由设备模型的上层构件(bus device driver class)在注册的时候调用它们内含的kobject(设备模型的底层基石)的添加注册操作,而kobject的操作就调用sysfs文件系统的具体操作。

       这些结构体是有联系的,但这一次我们先不过度关注他们的联系,仅仅对sysfs下目录和文件的创建做个分析:

       先看结构体kobject和sysfs_dirent:

[cpp] view plain copy
  1. struct kobject {  
  2.     const char      *name;  
  3.     struct list_head    entry;  
  4.     struct kobject      *parent;  
  5.     struct kset     *kset;  
  6.     struct kobj_type    *ktype;  
  7.     struct sysfs_dirent *sd;  
  8.     struct kref     kref;  
  9.     unsigned int state_initialized:1;  
  10.     unsigned int state_in_sysfs:1;  
  11.     unsigned int state_add_uevent_sent:1;  
  12.     unsigned int state_remove_uevent_sent:1;  
  13.     unsigned int uevent_suppress:1;  
  14. };  
  15.   
  16. struct sysfs_dirent {  
  17.     atomic_t        s_count;  
  18.     atomic_t        s_active;  
  19. #ifdef CONFIG_DEBUG_LOCK_ALLOC  
  20.     struct lockdep_map  dep_map;  
  21. #endif  
  22.     struct sysfs_dirent *s_parent;  
  23.     struct sysfs_dirent *s_sibling;  
  24.     const char      *s_name;  
  25.   
  26.     union {  
  27.         struct sysfs_elem_dir       s_dir;  
  28.         struct sysfs_elem_symlink   s_symlink;  
  29.         struct sysfs_elem_attr      s_attr;  
  30.         struct sysfs_elem_bin_attr  s_bin_attr;  
  31.     };  
  32.   
  33.     unsigned int        s_flags;  
  34.     unsigned short      s_mode;  
  35.     ino_t           s_ino;  
  36.     struct sysfs_inode_attrs *s_iattr;  
  37. };  

       sysfs_dirent结构中的union有四项:目录、链接文件,属性文件和二进制属性文件。


       我们vfs中有inodeentry两种关键的对象,在很多文件系统的设计中,都会有类似omfs_inodeomfs_extent_entry等等结构体来抽象表明具体文件系统的节点和目录项。

       而在sysfs中,不管是目录还是文件,都用同一个结构体sysfs_dirent来表示,这个结构体可以说是inodedentry的综合,因为有

      unsignedint s_flags;

              unsignedshort s_mode;

              ino_t s_ino;

       等类似于inode的内容,也有

             structsysfs_dirent *s_parent;

             structsysfs_dirent *s_sibling;

             constchar *s_name;

       等类似于dentry的内容。

       总的来说,sysfs_dirent结构体是sysfskobject建立连接的桥梁。

       我们知道,kobject对应于sysfs下的一个目录:

[cpp] view plain copy
  1. structsysfs_elem_dir {  
  2. structkobject    *kobj;  
  3. /*children list starts here and goes through sd->s_sibling */  
  4. structsysfs_dirent  *children;  
  5. };  

       上面的结构体紧密的将kobjectsysfs_dirent联系起来。kobject代表目录,而对于代表目录的sysfs_dirent,内嵌的sysfs_elem_dir有kobject的指针,所以kobject和sysfs_dirent

        是你中有我,我中有你。不过对于文件就不一样了,因为文件也有自己的sysfs_dirent,而文件并没有自己的kobject。

        在普通的文件系统中,比如omfs中,建立一个目录的话,首先会从物理存储介质(磁盘)中读取相关信息填充omfs下的omfs_inode结构体,然后会建立vfs层的inodedentry等结构体。

       而在sysfs中,在建立目录和文件时,只会通过sysfs_dirent结构体来建立目录文件的层次结构,而看不到vfs中的dentryinode。既然是Linux下的文件系统,不管多么特殊,肯定要有inodedentry的,sysfs文件系统也不例外,只不过sysfs将建立inodedentry的操作推到sysfs_lookup函数中来做,在sysfs_lookup中还会建立dentrysysfs_dirtnt的关系。dentry->d_fsdata= sysfs_get(sd);

       其实这个关系,在sysfs_fill_super就有体现:

root->d_fsdata= &sysfs_root;

[cpp] view plain copy
  1. struct sysfs_dirent sysfs_root = {  
  2.     .s_name     = "",  
  3.     .s_count    = ATOMIC_INIT(1),  
  4.     .s_flags    = SYSFS_DIR,  
  5.     .s_mode     = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,  
  6.     .s_ino      = 1,  
  7. };  

       这个sysfs_root就是sysfs_dirent层次结构中的根。

        下面是sysfs创建目录的过程,注意的是这个过程只能通过kobject的操作来实现,在/sys下用mkdir是没作用的

[cpp] view plain copy
  1. int sysfs_create_dir(struct kobject * kobj)  
  2. {  
  3.     struct sysfs_dirent *parent_sd, *sd;  
  4.     int error = 0;  
  5.   
  6.     BUG_ON(!kobj);  
  7.   
  8.     if (kobj->parent)  
  9.         parent_sd = kobj->parent->sd;  
  10.     else  
  11.         parent_sd = &sysfs_root;  
  12.   
  13.     error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);  
  14.     if (!error)  
  15.         kobj->sd = sd;  
  16.     return error;  
  17. }  


[cpp] view plain copy
  1. static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,  
  2.               const char *name, struct sysfs_dirent **p_sd)  
  3. {  
  4.     umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;  
  5.     struct sysfs_addrm_cxt acxt;  
  6.     struct sysfs_dirent *sd;  
  7.     int rc;  
  8.   
  9.     /* allocate */  
  10.     sd = sysfs_new_dirent(name, mode, SYSFS_DIR);   //初始化sysfs_dirent结构体  
  11.     if (!sd)  
  12.         return -ENOMEM;  
  13.     sd->s_dir.kobj = kobj;              //sysfs_dirent与kobject的联系建立  
  14.   
  15.     /* link in */  
  16.     sysfs_addrm_start(&acxt, parent_sd);  
  17.     rc = sysfs_add_one(&acxt, sd);  
  18.     sysfs_addrm_finish(&acxt);  
  19.   
  20.     if (rc == 0)  
  21.         *p_sd = sd;  
  22.     else  
  23.         sysfs_put(sd);  
  24.     return rc;  
  25. }  

         在sysfs_add_one是层次关系的建立:

[cpp] view plain copy
  1. int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)  
  2. {  
  3.     struct sysfs_inode_attrs *ps_iattr;  
  4.   
  5.     if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))  
  6.         return -EEXIST;  
  7.   
  8.     sd->s_parent = sysfs_get(acxt->parent_sd);       //建立上下层次间的父子关系  
  9.   
  10.     sysfs_link_sibling(sd);                        //建立同一层次的兄弟关系  
  11.   
  12.     /* Update timestamps on the parent */  
  13.     ps_iattr = acxt->parent_sd->s_iattr;                      
  14.     if (ps_iattr) {  
  15.         struct iattr *ps_iattrs = &ps_iattr->ia_iattr;  
  16.         ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;  
  17.     }  
  18.   
  19.     return 0;  
  20. }  

        在sysfs_link_sibling中关键代码:

[cpp] view plain copy
  1. for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) {  
  2.     if (sd->s_ino < (*pos)->s_ino)  
  3.         break;  
  4. }  

          根据s_ino从小到大的顺序组成一个链。

           附上一个图,这个关系就一目了然:


从这个图可以很清楚的看到sysfs中sysfs_dirent架成的树形结构(注意他们的s_ino排列),这个结构和kobject,dentry的树形结构几乎一致,因为他们是有联系的,后面我们会一步步理清他们的联系,到时侯就明白sysfs是如何将设备模型(kobject)倒成文件系统的。

    上面的图没有画全,bus-->class-->firmware-->kernel-->power-->module-->block.



阅读全文
0 0