【转】Linux那些事儿之我是Sysfs(10)sysfs 创建目录 - wilson的日...

来源:百度文库 编辑:神马文学网 时间:2024/07/09 00:59:22
最新日志
  • (转)标准 BT656 并行 数据结
  • ITU601/656简介
  • OpenMP和MPI比较(转)
  • MPI简介(转)
  • mii-tools的源代码学习(转)
  • 单片机访问IIC总线技术

博主推荐

    相关日志

      随机阅读

      • 解开管理基因的秘密
      • “中国菊”和“非洲菊”
      • 何不将江青墓迁到重庆实名厚葬(图)
      • [转载]从多金到多毛──论亦舒笔下男子形象之变迁
      • 儿童期父母离婚与成年期中风有关
      • 独家:女明星亲身试穿:贝嫂家的紧身裙到底能瘦多少?

      首页推荐

      • 闺蜜恋父偷爱上我公公
      • 鬼斧神工的一组照片
      • 日本人的最牛发明
      • 旧上海妓女是时尚先锋
      • 20亿贪官如何移动?
      • 局长撞死人也公费报销
      更多>>

        【转】Linux那些事儿之我是Sysfs(9)sysfs文件系统模型   【转】Linux那些事儿之我是Sysfs(11)sysfs 创建普通文件

      【转】Linux那些事儿之我是Sysfs(10)sysfs 创建目录

      linux kernel 2009-07-14 16:32:02 阅读53 评论0   字号:大小 订阅

      每当我们新增一个kobject结构的时候,同时会在/sys下创建一个目录。

      kobject_add()  ->  create_dir() -> sysfs_create_dir()

      此时,我还想重申,kernel代码的更新换代是很快的,我们的目的是懂得代码背后的原理,知识,或曰哲学。我不想讲的太细,因为关于sysfs的部分从 2.6.10到现在2.6.22已经改了很多了。但其总体架构没变。写此文的目的是让您跟着我的思路走一遍,对sysfs有了一个总体上的认识。然后自己就可以去看最新的代码了。最新的代码肯定是效率更高,条理逻辑更清晰。

      sysfs_create_dir()流程图如下:
                           -> create_dir()
                                                -> *d = sysfs_get_dentry()
                                                                     -> lookup_hash()
                                                                                          -> __lookup_hash()
                                                                                          -> cached_lookup()
                                                                                          -> new = d_alloc(base, name);
                                                                                          -> inode->i_op->lookup(inode, new, nd)
                                                -> sysfs_create(*d, mode, init_dir)
                                                                     -> sysfs_new_inode(mode)
                                                                     -> init_dir(inode); \\ Call back function
                                                -> sysfs_make_dirent()
                                                                     -> sysfs_new_dirent()
                                                                     -> dentry->d_fsdata = sysfs_get(sd);
                                                                     -> dentry->d_op = &sysfs_dentry_ops;
                                                -> (*d)->d_op = &sysfs_dentry_ops;

          135 int sysfs_create_dir(struct kobject * kobj)
          136 {
          137         struct dentry * dentry = NULL;
          138         struct dentry * parent;
          139         int error = 0;
          140
          141         BUG_ON(!kobj);
          142
          143         if (kobj->parent)
          144                 parent = kobj->parent->dentry;
          145         else if (sysfs_mount && sysfs_mount->mnt_sb)
          146                 parent = sysfs_mount->mnt_sb->s_root;
          147         else
          148                 return -EFAULT;
          149
          150         error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
          151         if (!error)
          152                 kobj->dentry = dentry;
          153         return error;
          154 }
      143-148就是找到父辈的kobject,再调用create_dir();

           95 static int create_dir(struct kobject * k, struct dentry * p,
           96                       const char * n, struct dentry ** d)
           97 {
           98         int error;
           99         umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
          100
          101         down(&p->d_inode->i_sem);
          102         *d = sysfs_get_dentry(p,n);
          103         if (!IS_ERR(*d)) {
          104                 error = sysfs_create(*d, mode, init_dir);
          105                 if (!error) {
          106                         error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
          107                                                 SYSFS_DIR);
          108                         if (!error) {
          109                                 p->d_inode->i_nlink++;
          110                                 (*d)->d_op = &sysfs_dentry_ops;
          111                                 d_rehash(*d);
          112                         }
          113                 }
          114                 if (error && (error != -EEXIST))
          115                         d_drop(*d);
          116                 dput(*d);
          117         } else
          118                 error = PTR_ERR(*d);
          119         up(&p->d_inode->i_sem);
          120         return error;
          121 }
      99行,设置‘文件’ 属性,101获取信号量。

      (1)sysfs_get_dentry()
      102 行sysfs_get_dentry()。它的作用是根据父辈dentry和文件名得到dentry结构。首先在缓存中找,如果找到就返回,找不到就用 d_alloc()新建一个dentry结构。我们是新建文件夹,缓存中自然是没有的,所以要用d_alloc()来新建一个。接着我们调用lookup 函数,它定义如下。

      struct inode_operations sysfs_dir_inode_operations = {
                   .lookup = sysfs_lookup,
      };

          204 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
          205                                 struct nameidata *nd)
          206 {
          207         struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
          208         struct sysfs_dirent * sd;
          209         int err = 0;
          210
          211         list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
          212                 if (sd->s_type & SYSFS_NOT_PINNED) {
          213                         const unsigned char * name = sysfs_get_name(sd);
          214
          215                         if (strcmp(name, dentry->d_name.name))
          216                                 continue;
          217
          218                         if (sd->s_type & SYSFS_KOBJ_LINK)
          219                                 err = sysfs_attach_link(sd, dentry);
          220                         else
          221                                 err = sysfs_attach_attr(sd, dentry);
          222                         break;
          223                 }
          224         }
          225
          226         return ERR_PTR(err);
          227 }

      前面讲过lookup函数的作用。它在inode代表的文件夹下查找有没有名为dentry.d name.name的文件。如果有,就将其对应的inode结构从信息的载体中读出来。由于是新建的文件夹,所以lookup函数在我们这个故事里根本没做事。但是我还是忍不住想分析一下lookup函数。

      sysfs文件系统中,文件夹的inode和dentry结构一直都是存在于内存中的,所以不用再进行读取了。而文件,链接的inode事先是没有的,需要从载体中读出。这就是212行这个判断的作用。可以看出,如果是文件夹,循环里面啥都没做。

      #define SYSFS_NOT_PINNED \
      (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)

      但是sysfs的lookup还有它不同之处。其他文件系统像ext3格式中普通文件的inode,在文件创建之时就已经创建了。但是,sysfs不一样,它在创建普通文件时,只是先创建一个sysfs_dirent结构。创建inode的工作是推迟到lookup函数来完成的。在下一节 sysfs_create_file()会看到这一点。

      sysfs_attach_attr()和sysfs_attach_link()的作用就是根据dentry和sysfs_dirent新建一个inode。

      总之,我们通过sysfs_get_dentry()得到了一个新建的dentry结构。

      (2)sysfs_create()分析 (104行)
      sysfs_create()->sysfs_new_inode(mode) -> new_inode(sysfs_sb)
      创建一个新的索引节点inode。sysfs_sb是sysfs的超级块(super_block)结构。mode则是inode的属性,它记录了如下信息,比如,文件类型(是文件夹,链接,还是普通文件),inode的所有者,创建时间等等。

      (3)sysfs make dirent()分析 (104行)
      至此,我们得到了一个dirent结构,初始化,再把它连接到上层目录的sysfs_dirent的s_children链表里去。sysfs_make_dirent()为刚刚新建出来的dentry建立一个dirent结构。并将dentry和dirent联系起来。

      (4)总结
      在sysfs下创建一个目录,提供的函数是sysfs_create_dir()。创建了dentry, dirent, inode
      结构, 它们之间的连接关系见图1

        0人  |  分享到:          阅读(53)| 评论(0)| 引用(0) |举报   【转】Linux那些事儿之我是Sysfs(9)sysfs文件系统模型   【转】Linux那些事儿之我是Sysfs(11)sysfs 创建普通文件