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

  • 相关阅读:
    解Bug之路-记一次存储故障的排查过程
    自己动手写SQL执行引擎
    从linux源码看socket(tcp)的timeout
    解Bug之路-记一次JVM堆外内存泄露Bug的查找
    从linux源码看epoll
    可拖拽圆形进度条组件(支持移动端)
    Threejs模仿实现滴滴官网首页地球动画
    css实现朋友圈照片排列布局
    H5页面设置title,解决设置默认title为空时闪烁问题
    vue-cli3.0本地代理cookie跨域请求Nginx配置
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/8372710.html
Copyright © 2011-2022 走看看