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

原创 2007年09月11日 18:57:00

每当我们新增一个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

版权声明:本文为博主原创文章,未经博主允许不得转载。

sysfs以及 /sys文件夹相关知识

使用 /sys 文件系统访问 Linux 内核 sysfs 虚拟文件系统提供了一种比 proc 更为理想的访问内核数据的途径 sysfs 是 Linux 内核中设计较新的一...
  • dhgao38
  • dhgao38
  • 2014年04月24日 11:46
  • 3065

linux内核sysfs详解

"sysfs is a ram-based filesystem initially based on ramfs. It provides a means to export kernel dat...
  • skyflying2012
  • skyflying2012
  • 2013年09月17日 18:35
  • 19671

使用sysfs创建LED驱动

有了前面两个实验,我们就可以依葫芦画瓢,实现自己想要的驱动了。本实验通过sysfs,即前面的kobject实现LED灯的控制。默认x4412开发板已经将LED驱动集成进去了,但是它使用的linux内核...
  • bzw73
  • bzw73
  • 2015年06月19日 21:17
  • 1028

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

每当我们新增一个kobject结构的时候,同时会在/sys下创建一个目录。 kobject_add()  ->  create_dir() -> sysfs_create_dir() 此时,我还想重申...
  • zhqh100
  • zhqh100
  • 2015年03月20日 16:19
  • 831

Linux那些事儿 之 我是Sysfs上.pdf

  • 2009年03月14日 12:52
  • 364KB
  • 下载

Linux那些事儿(包括Hub, Sysfs, UHCI, USB, U盘5个部分)

  • 2009年03月02日 10:43
  • 5.18MB
  • 下载

Linux那些事儿之我是Sysfs

  • 2010年02月03日 16:20
  • 826KB
  • 下载

Linux那些事儿之我是Sysfs

  • 2010年01月10日 10:54
  • 860KB
  • 下载

Linux那些事儿之我是sysfs

  • 2013年04月24日 15:22
  • 970KB
  • 下载

Linux那些事儿之我是Sysfs

  • 2011年01月10日 11:03
  • 758KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux那些事儿之我是Sysfs(10)sysfs 创建目录
举报原因:
原因补充:

(最多只允许输入30个字)