sysfs 文件系统简单分析

01int __init sysfs_init(void)
02{
03 int err = -ENOMEM;
04
05 sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
06           sizeof(struct sysfs_dirent),
07           0, 0, NULL);
08 if (!sysfs_dir_cachep)
09  goto out;
10
11 err = sysfs_inode_init();
12 if (err)
13  goto out_err;
14
15 err = register_filesystem(&sysfs_fs_type);
16 if (!err) {
17  sysfs_mount = kern_mount(&sysfs_fs_type);
18  if (IS_ERR(sysfs_mount)) {
19   printk(KERN_ERR "sysfs: could not mount!\n");
20   err = PTR_ERR(sysfs_mount);
21   sysfs_mount = NULL;
22   unregister_filesystem(&sysfs_fs_type);
23   goto out_err;
24  }
25 } else
26  goto out_err;
27out:
28 return err;
29out_err:
30 kmem_cache_destroy(sysfs_dir_cachep);
31 sysfs_dir_cachep = NULL;
32 goto out;
33}
第5行对sysfs_dir_cachep指针分配空间  
第15行注册sysfs文件系统。  
第17行挂载sysfs文件系统。  
第18-23行挂载文件系统失败后,会卸载文件系统。  
第29-32行注册文件系统失败后,所做的一些处理,销毁分配的内存,设置sysfs_dir_cachep的指针为空。

1static struct file_system_type sysfs_fs_type = {
2 .name  = "sysfs",
3 .get_sb  = sysfs_get_sb,
4 .kill_sb = kill_anon_super,
5};

第2行文件系统的名字
第3行分配超级块
第4行卸载文件系统后,释放超级块所占有的资源
1static int sysfs_get_sb(struct file_system_type *fs_type,
2 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
3{
4 return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
5}

01int get_sb_single(struct file_system_type *fs_type,
02 int flags, void *data,
03 int (*fill_super)(struct super_block *, void *, int),
04 struct vfsmount *mnt)
05{
06 struct super_block *s;
07 int error;
08
09 s = sget(fs_type, compare_single, set_anon_super, NULL);
10 if (IS_ERR(s))
11  return PTR_ERR(s);
12 if (!s->s_root) {
13  s->s_flags = flags;
14  error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
15  if (error) {
16   deactivate_locked_super(s);
17   return error;
18  }
19  s->s_flags |= MS_ACTIVE;
20 }
21 do_remount_sb(s, flags, data, 0);
22 simple_set_mnt(mnt, s);
23 return 0;
24}

第9行调用sget()函数分配新的超级块,传递set_anon_super()函数的地址作为参数。用合适的方式设置超级块的s_dev字段。
第10行将flags参数的值拷到超级块的s_flags字段中。
第11行的函数指针指向sysfs_fill_super函数,来分配索引节点对象和对应的目录项对象,并填充超级块字段的值。

01static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
02{
03 struct inode *inode;
04 struct dentry *root;
05
06 sb->s_blocksize = PAGE_CACHE_SIZE;
07 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
08 sb->s_magic = SYSFS_MAGIC;
09 sb->s_op = &sysfs_ops;
10 sb->s_time_gran = 1;
11 sysfs_sb = sb;
12
13 /* get root inode, initialize and unlock it */
14 mutex_lock(&sysfs_mutex);
15 inode = sysfs_get_inode(&sysfs_root);
16 mutex_unlock(&sysfs_mutex);
17 if (!inode) {
18  pr_debug("sysfs: could not get root inode\n");
19  return -ENOMEM;
20 }
21
22 /* instantiate and link root dentry */
23 root = d_alloc_root(inode);
24 if (!root) {
25  pr_debug("%s: could not get root dentry!\n",__func__);
26  iput(inode);
27  return -ENOMEM;
28 }
29 root->d_fsdata = &sysfs_root;
30 sb->s_root = root;
31 return 0;
32}
33

第6行给超级块的文件的最长长度赋值
第7行给超级块的字节为单位的块大小的字段赋值
第9行超级块的方法指向sysfs_ops结构体的地址
第10行超级块时间戳的粒度赋值
第11行把超级块的指针赋给全局的指针syssb
第14行对变量sysfs_mutex加锁
第15行得到sysfs_dirent的节点,如果没有这个节点,分配新的节点,如果有的话,利用哈希表的方式找出来。
第23行实例和链接根目录
第29行root的d_fsdata字段指向sysfs_root。
第30行超级块的根目录指向root目录

01struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
02{
03 struct inode *inode;
04
05 inode = iget_locked(sysfs_sb, sd->s_ino);
06 if (inode && (inode->i_state & I_NEW))
07  sysfs_init_inode(sd, inode);
08
09 return inode;
10}

第5行从挂载的文件系统中获得节点,使用ifind_fast函数搜索结点按节点号在inode 缓存里面。如果出现,增加一个引用,如果节点不在缓存里面,调用get_new_inode_fast函数返回一个新节点。
第7行初始化一个新节点

01static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
02{
03 struct bin_attribute *bin_attr;
04
05 inode->i_private = sysfs_get(sd);
06 inode->i_mapping->a_ops = &sysfs_aops;
07 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
08 inode->i_op = &sysfs_inode_operations;
09 inode->i_ino = sd->s_ino;
10 lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
11
12 if (sd->s_iattr) {
13  /* sysfs_dirent has non-default attributes
14   * get them for the new inode from persistent copy
15   * in sysfs_dirent
16   */
17  set_inode_attr(inode, sd->s_iattr);
18 } else
19  set_default_inode_attr(inode, sd->s_mode);
20
21
22 /* initialize inode according to type */
23 switch (sysfs_type(sd)) {
24 case SYSFS_DIR:
25  inode->i_op = &sysfs_dir_inode_operations;
26  inode->i_fop = &sysfs_dir_operations;
27  inode->i_nlink = sysfs_count_nlink(sd);
28  break;
29 case SYSFS_KOBJ_ATTR:
30  inode->i_size = PAGE_SIZE;
31  inode->i_fop = &sysfs_file_operations;
32  break;
33 case SYSFS_KOBJ_BIN_ATTR:
34  bin_attr = sd->s_bin_attr.bin_attr;
35  inode->i_size = bin_attr->size;
36  inode->i_fop = &bin_fops;
37  break;
38 case SYSFS_KOBJ_LINK:
39  inode->i_op = &sysfs_symlink_inode_operations;
40  break;
41 default:
42  BUG();
43 }
44
45 unlock_new_inode(inode);
46}

第6行对索引节点的指向address_space对象的方法赋值(后面会分析)
第7行对索引节点的指向address_space对象的设备信息赋值
第8行索引节点的方法指向sysfs_inode_operations
下面是根据索引节点的类型,分别进行初始化。
第24行如果索引节点是目录,分别对索引节点的方法进行赋值。
第29行如果索引节点是属性文件,分别对其赋值
第33行如果索引节点是二进制文件,分别对其赋值。
第38行如果是链接文件,对它的方法进行初始化。

01struct dentry * d_alloc_root(struct inode * root_inode)
02{
03 struct dentry *res = NULL;
04
05 if (root_inode) {
06  static const struct qstr name = { .name = "/", .len = 1 };
07
08  res = d_alloc(NULL, &name);
09  if (res) {
10   res->d_sb = root_inode->i_sb;
11   res->d_parent = res;
12   d_instantiate(res, root_inode);
13  }
14 }
15 return res;
16}

第5行判断root_inode的节点是否为真。
第6行对name结构体初始化
第8行分配一个dcache 目录
第10行目录项的超级块指向指向索引节点的超级块指针
第11行目录项的父指针指向自己
第12填充索引节点信息为根目录。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值