Chinaunix首页 | 论坛 | 博客
  • 博客访问: 122978
  • 博文数量: 19
  • 博客积分: 942
  • 博客等级: 准尉
  • 技术积分: 228
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-08 20:41
文章分类
文章存档

2013年(2)

2012年(5)

2011年(12)

分类: LINUX

2013-01-07 00:43:46

这两天看文件系统, 这是第3遍了吧, 至少。总是看了, 忘了, 再看, 虽然每一次都似乎能看出点新的之前没注意到的内容, 但一遍遍的忘记实在让人恼火, 这一次, 将现在记住的背诵下来, 看看有没有点效果? 恩, 是的, 以下内容绝大部分是直接从记忆中取得的, 有一点没记住, 看了看书

struct inode 里面有 15 个成员最为重要, 分成4类:

1. 链表类,

i_hash 将 inode 链接入 inode hashtable, 外部可以通过 super_block 指针与 ino 来找到这个 inode

i_dentry 为 inode 的 dentry 链表表头, 从而一个 inode 可以在文件树中有多个硬链接

i_list 将 inode 链接入 inode_used 链表

2. 属性类

i_ino,  inode  number

i_mode, 文件 RWX 属性及文件类型, 比如是否是文件夹, 普通文件, 或者设备文件等

i_dev,  inode 所在设备的设备号, 从 super_block->s_dev 中来;而 super_block->s_dev 一般从 bdev->bd_dev 而来, 而 bdev 是该设备文件在 devfs 中的 inode 初始化时创建的, bdev->bd_dev 一般来自该设备文件的 inode->rdev, 而 redev 其实就是在devfs 中mknod 时的主设备/从设备号而来; 转了一大圈, 最终效果是 mknod 指定的设备号被赋予该设备 super block 及 inode 中的 dev 信息。

i_rdev, 这个和上面的其实是相关的, devfs 中的设备文件在内存中创建 inode 结构时, 会最终将该设备的设备号经过二进制逻辑操作而生成 i_rdev 记录在 devfs 中的 inode 的  i_rdev 里面, 以后, 如果mount 这个设备, 这个 rdev 又会记录在被 mount 进的设备的 super block及 inode 中

i_nlink, 硬链接数

i_count,  inode 引用计数

3. 指针类

i_op, inode_operations 结构指针, read_inode 时根据 inode 类型(保存在 i_mode中) 进行指定

i_fop, file_operaitons 结构指针,  read_inode 时根据 inode 类型(保存在 i_mode中) 进行指定

i_sb, super_block 指针

i_mapping, address_space 结构指针, 和页面交换相关

4. 特殊类

比如 i_pipe, 应该只有 inode 为管道时才有意义

i_bdev, 也只有 inode 为块设备文件时才会有意义。

 

其余还有些成员, 比如 gid, uid 之类, 从文件系统自身实现及与其他子系统联系看, 没什么太重要的, 重要的应该是上面这些。

文件系统几个函数跳转表总结一下:

super block operations 在 read_super 时赋给 super_block->s_op 指针

file_operations, inode_operations 都是在 read_inode时根据 inode 的不同类型赋得值, 保存在  inode->i_op, inode->i_fop 中

dentry_operations 是在 inode->i_op->lookup 时赋值给被 lookup 的 dentry 的 f_op 成员的

 

而 read_super 是文件系统数据结构的成员, 典型 mount 命令如:

mount -t ext2 /dev/hdxxx /mnt/tmp 命令行包含了几个信息:

1. 文件系统类型, 这里是 ext2, 从这里就能得到 read_super 函数指针

2. 设备文件, 这里是 /dev/hdxxx. 从这里得到路径名, 从而可以通过 path_walk 获得该设备文件的 dentry, 及 inode, 并在初始化 inode 的时候获得其  rdev 并创建 bdev, inode 保持其一个引用, 至于 bdev 的 block_device_operations 指针则要么通过 rdev 号为下标从内核全局数组 blddevs 获得, 或者靠其  inode为下标 从另一个全局数组中获得

3. 挂载点, 这里是 /mnt/tmp, 同样可以通过 path_walk 获得其 dentry;

通过这些信息,  bdev 执行 bdev->bd_op->open 操作, 如果成功, 则执行 fs->read_super 操作, 如果也成功, 则被打开的 bdev 会有一个引用保存在 super block 中, 由于此, 在mount结束阶段, 释放 /dev/hdxxx 对应的dentry 时, 同时也会因为有 inode 的释放进一步导致 bdev的释放(inode 保持其一个引用), 如果没有 super block 这个引用, bdev 就真的释放了。

 

再得到super_block 之后, mount 过程继续, 会调用 add_vfsmount, 在这个函数里, 会创建一个 vfsmount结构, vfsmount 结构有如下重要成员:

1. 指针类

mnt_parent, 指向上一级 vfsmount 结构, 也就是这里的 /mnt/tmp 所在的设备的挂在点的 vfsmount 结构

mnt_mountpoint, 指向 /mnt/tmp 的 dentry 结构

mnt_root, 指向新创建的 superblock 的 s_root dentry 结构, 这个结构是 read_super 时创建的该设备的根目录

mnt_sb, 指向新创建的 super_block 

2. 链表类

mnt_child, 将这个  vfsmount结构链接入上一级 vfsmount 的 mnt_mounts 链表

mnt_clash, 将这个 vfsmount 结构链接入 mnt_mountpoint 的 d_vfsmnt 链表

mnt_mounts, 自己的子 vfsmount 链表表头, 用来链将来的下一级vfsmount 的

mnt_instance, 将这个 vfsmount 结构链接入 super_block 的 s_mounts 链表, 因为一个设备可以被同时挂载到不同的路径上, 因此, vfsmount 与 super block 也是 多 对 1 的关系

mnt_list 将这个 vfsnount 结构链接入一个链接所有的 vfsmount 的链表

将这些指针与链接操作完毕后, mount 也就完成了, 从文件树向下, 如果发现一个 dentry->d_vfsmnt 链表非空, 就可知为一个挂载点, 根据 vfsmnt 中保存的 mnt_root 信息, 即可得到下一个设备的 dentry, 通过保存的 mnt_sb 可以得到下一级设备的超级块, 通过替换当前身为挂在点的dentry为 mnt_root, 即走到了下一个设备


阅读(3083) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~