zoukankan      html  css  js  c++  java
  • sysfs文件系统的建立【转】

    http://blog.csdn.net/dndxhej/article/details/7434615

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

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

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

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

    kobject结构体:

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

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

    struct sysfs_dirent {
        atomic_t        s_count;
        atomic_t        s_active;
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map    dep_map;
    #endif
        struct sysfs_dirent    *s_parent;
        struct sysfs_dirent    *s_sibling;
        const char        *s_name;
    
        union {
            struct sysfs_elem_dir        s_dir;
            struct sysfs_elem_symlink    s_symlink;
            struct sysfs_elem_attr        s_attr;
            struct sysfs_elem_bin_attr    s_bin_attr;
        };
    
        unsigned int        s_flags;
        unsigned short        s_mode;
        ino_t            s_ino;
        struct sysfs_inode_attrs *s_iattr;
    };

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

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

    1 unsignedint s_flags;
    2 unsignedshort s_mode;
    3 ino_t s_ino;

     等类似于inode的内容,也有:

    1 structsysfs_dirent *s_parent;
    2 structsysfs_dirent *s_sibling;
    3 constchar *s_name;

    等类似于dentry的内容。

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

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

    1 structsysfs_elem_dir {
    2 structkobject     *kobj;
    3 /*children list starts here and goes through sd->s_sibling */
    4 structsysfs_dirent    *children;
    5 };

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

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

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

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

    其实这个关系,在sysfs_fill_super就有体现:root->d_fsdata= &sysfs_root;

    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是没作用的:

     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 }
     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是层次关系的建立:

     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中关键代码:

    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)倒成文件系统的。

  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/8372710.html
Copyright © 2011-2022 走看看