etx2文件系统inode
时间:2010-09-14 来源:yulf88
一.inode size 定义 | |||||
|
|
|
|
|
|


<!--[endif]-->
inode size 倒底要多大才比较好?有人说如果小档案多,则以 1024 byte 较好。
这样的思考原则好像不是很谨慎。多少才叫『多』呢?我想我们需要一点定量的分析才对。
首先我们来『观察』一下 inode size 大小对我们 filesystem (以下 filesystem 均简称 fs) 及系统的相对性影响:
inode size 越小,inode table 越肥,可用空间越小。
inode size 越小,link 就越长,越会拖慢速度。
inode size 越小,空间利用率就越高。
此外,因为 x86 的 pagesize=4K 的特性,在做 mmap() 及 swap 这类的 virtual memory 动作时,如果 inode size 为 4K 的倍数,将较有效率。
所以,看来 inode size <4K 除了空间利用率较高以外,其馀全都是缺点。
而就一般实际经验来讲,空间利用率的提高,并不足以弥补因 inode table 的肥大而浪费掉的空间......所以一般而言 4K 是一个不错的经验值。
上面最後一点,我们提到了『空间利用率的提高,并不足以弥补因 inode table 的肥大而浪费掉的空间』一个事实;它的确是一个事实,除非您的 fs 是专供 BBS 这种系统而使用。以下是一些参考数据:
表一: inode size 和 inode table 大小关系 inode size(byte) inode table 在该 fs 上所占掉的百分比
1024 12.57% (约 1/8)
2048 6.31% (约 1/4)
4096 3.19%
8192 1.63%
16384 0.84%
32768 0.45%
所以以一个 1GB 的 partition 来造 fs 为例,不同的 inode size 将会立刻 先使用掉的容量 (拿去存 inode table 了) 是:
表二: inode size 与 inode table 大小 (在 1GB fs 中) inode size(byte) inode table 大小
1024 128.7MB
2048 64.6MB
4096 32.6MB
馀类推
试想,一个 1GB 的 fs 就只为了 inode size=1024 而就先用掉了 128MB 的空间, 除非将来我们的小档案真的很多很多,不然是补不回来的。
再来我们举例比较一下 inode size=1024 与 inode size=2048 的 fs:
以一个大小不到 1k 的档存在 inode size=1024 的 fs 中,是比在 inode size=2048 的 fs 中省下了 1k 的空间;但在 1GB 的 fs □, 要有 (128.7-64.6) * 1024 = 65614 个这样多的小档案,才算是『赚到了』; 呵呵.....你的 fs □凑得出这麽多小於 1k 的档吗?
类推 512MB 的 fs □,就要有 32820 个小於 1k 的档才算『赚到了』。
小於 1k 的档,除非你是开 bbs 的,不然在同一个 file system 上 想凑出 10000 个都很难;
我想,不再举个更实际的例子,恐怕还是有人不信。 以下是我以前对某个 1GB fs 中的 file size 统计:
表三: 本人某个旧 1GB fs 中的 file size 统计: 档案大小的□围 该大小□围内的档案个数
不到1K的 6538
1-2K 2053
2-4K 1565
4-8K 1064
8-16K 1011
16-32K 595
32K以上 1112
OK,看起来很明显地,不满 1k 大小的档案个数,已经占了快一半了; 所以直觉上会认为 inode size=1024 比较好?错了......
以下是以 inode size 来看 (fs 为 1GB 大小) 相对浪费空间的大小:
表四: 档案空间相对浪费大小与 inode size 对应表: inode size(byte) 档案空间相对浪费大小加上 inode table 大小
1024 131766KB (即 inode table 大小)
2048 72743KB (inode table size + 1K*6538)
4096 57208KB (inode table size + 3K*6538 + 2K*2053)
8192 81410KB (inode table size + 7K*6538 + 6K*2053.....)
16384 162959KB (馀请类推)
32768 354549KB
所以反而以 inode size=4k 最佳。
上面那些『空间相对浪费大小』计算上有点复杂, 不另说明. (呵呵, 搞不好我的算法是错的......所以不敢公布算法)
以同样的分析来看我的 bbs 的情况, inode size=1024 是最佳的, 因为小於 1k 的档案竟然多达四万个以上.
/usr 分析出来是以 inode size=2048 最佳。
但请注意, 以上只是空间利用率的分析, 不是速度上的分析...转自:http://blog.chinaunix.net/u/12909/showart_2041325.html
什么是super block
一、预备知识
1、block
对于ext2(ext3类似)文件系统来说,硬盘分区首先被划分为一个个的block,同一个ext2文件系统上的每个block大小都是一样的。但是对于不同的ext2文件系统,block的大小可以有区别。典型的block大小是1024 bytes或者4096 bytes。这个大小在创建ext2文件系统的时候被决定,它可以由系统管理员指定,也可以由文件系统的创建程序根据硬盘分区的大小,自动选择一个较合理的值。
一个硬盘分区上的block计数是从0开始的,并且这个计数对于这个硬盘分区来说是全局性质的。
2、block group和group descriptor
硬盘分区中所有block被聚在一起分成几个大的block group,其中每个block group中有多少个block是固定的。
每个block group都相对应一个group descriptor,这些group descriptor被聚在一起放在硬盘分区的开头部分,跟在super block的后面。在每个group descriptor当中有几个重要的block指针,指向block group的inode table、block bitmap和inode bitmap。
3、inode table、block bitmap和inode bitmap
以上三个结构记载了其所属block group的许多信息,他们依次被存放在这个block group的开头部分,由该block group所对应的group descriptor中的指针所指向。
二、super block的定义
super block的中文名称是超级块,它是硬盘分区开头——开头的第一个byte是byte 0,从 byte 1024开始往后的一部分数据。由于 block size最小是 1024 bytes,所以super block可能是在block 1中(此时block 的大小正好是 1024 bytes),也可能是在block 0中。
超级块中的数据其实就是文件卷的控制信息部分,也可以说它是卷资源表,有关文件卷的大部分信息都保存在这里。例如:硬盘分区中每个block的大小、硬盘分区上一共有多少个block group、以及每个block group中有多少个inode。(下有详细说明)
三、super block的结构和涵义
struct ext3_super_block {
/*00*/ __u32 s_inodes_count; /* inodes 计数 */
__u32 s_blocks_count; /* blocks 计数 */
__u32 s_r_blocks_count; /* 保留的 blocks 计数 */
__u32 s_free_blocks_count; /* 空闲的 blocks 计数 */
/*10*/ __u32 s_free_inodes_count; /* 空闲的 inodes 计数 */
__u32 s_first_data_block; /* 第一个数据 block */
__u32 s_log_block_size; /* block 的大小 */
__s32 s_log_frag_size; /* 可以忽略 */
/*20*/ __u32 s_blocks_per_group; /* 每 block group 的 block 数量 */
__u32 s_frags_per_group; /* 可以忽略 */
__u32 s_inodes_per_group; /* 每 block group 的 inode 数量 */
__u32 s_mtime; /* Mount time */
/*30*/ __u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic 签名 */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
/*40*/ __u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* 可以忽略 */
__u32 s_rev_level; /* Revision level */
/*50*/ __u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
/*60*/ __u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
/*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
/*78*/ char s_volume_name[16]; /* volume name */
/*88*/ char s_last_mounted[64]; /* directory where last mounted */
/*C8*/ __u32 s_algorithm_usage_bitmap; /* 可以忽略 */
__u8 s_prealloc_blocks; /* 可以忽略 */
__u8 s_prealloc_dir_blocks; /* 可以忽略 */
__u16 s_padding1; /* 可以忽略 */
/*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
/*E0*/ __u32 s_journal_inum; /* 日志文件的 inode 号数 */
__u32 s_journal_dev; /* 日志文件的设备号 */
__u32 s_last_orphan; /* start of list of inodes to delete */
/*EC*/ __u32 s_reserved[197]; /* 可以忽略 */
};
四、super block的几个重要成员
1、Magic 签名
对于ext2和ext3文件系统来说,这个字段的值应该正好等于0xEF53。如果不等的话,那么这个硬盘分区上肯定不是一个正常的ext2或ext3文件系统。
2、s_log_block_size
从这个字段,我们可以得出真正的block的大小。我们把真正block的大小记作B,B=1 << s_log_block_size + 10),单位是bytes。举例来说,如果这个字段是0,那么block的大小就是 1024bytes,这正好就是最小的block大小;如果这个字段是2,那么block大小就是4096 bytes。从这里我们就得到了block的大小这一非常重要的数据。
3、s_blocks_count和s_blocks_per_group
通过这两个成员,我们可以得到硬盘分区上一共有多少个block group,或者说一共有多少个group descriptors
s_blocks_count记录了硬盘分区上的block的总数,而s_blocks_per_group记录了每个group中有多少个block。显然,文件系统上的block groups数量,我们把它记作G,G=(s_blocks_count-s_first_data_block-1) /s_blocks_per_group+1。为什么要减去s_first_data_block,因为s_blocks_count是硬盘分区上全部的 block的数量,而在s_first_data_block之前的block是不归block group管的,所以当然要减去。最后为什么又要加一,这是因为尾巴上可能多出来一些block,这些block我们要把它划在一个相对较小的group 里面。
4、s_inodes_per_group
s_inodes_per_group记载了每个block group中有多少个inode。在从已知的inode号,读取这个inode数据的过程中,s_inodes_per_group起到了至关重要的作用。
用我们得到的inode号数除以s_inodes_per_group,我们就知道了我们要的这个inode是在哪一个block group里面,这个除法的余数也告诉我们,我们要的这个inode是这个block group里面的第几个inode;然后,我们可以先找到这个block group的group descriptor,从这个descriptor,我们找到这个group的inode table,再从inode table找到我们要的第几个 inode,再以后,我们就可以开始读取inode中的用户数据了。这个公式是这样的:
block_group = (ino - 1) / s_inodes_per_group。这里ino就是我们的inode号数
offset = (ino - 1) % s_inodes_per_group,这个offset就指出了我们要的inode是这个block group里面的第几个inode。
http://bbs.zdnet.com.cn/viewthread.php?tid=140406
图片转自:
http://blog.chinaunix.net/u2/61187/showart_2035823.html