Linux 文件系统的 Superblock, Inode, Dentry 和 File
2014-06-30 16:13
585 查看
参考文档:http://www.elmerzhang.com/2012/12/suerblock-inode-dentry-file-of-filesystem/ http://www.360doc.com/content/12/0322/14/6702151_196616602.shtml http://homepage.smc.edu/morgan_david/cs40/analyze-ext2.htm
http://blog.csdn.net/poechant/article/details/7214926
首先,Superblock, Inode, Dentry 和 File 都属于元数据(Metadata),根据维基百科中的解释,所谓元数据,就是描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件纪录等功能。Linux/Unix 文件系统的元数据以多级结构保存。
1、Inode 和 Block(1)背景 由于Linux系统是多用户多的,所以文件系统类型多样化是在所难免的。从ext2开始,是将文件属性和文件内容分开存储的,分别由inode和block来负责。
(2)inode 用于存储文件的各属性,包括: - 所有者信息:文件的owner,group; - 权限信息:read、write和excite; -时间信息:建立或改变时间(ctime)、最后读取时间(atime)、最后修改时间(mtime); - 标志信息:一些flags; - 内容信息:type,size,以及相应的block的位置信息。 注意:不记录文件名或目录名,文件名或目录名记录在文件所在目录对应的block里。
(3)block 用来存储文件的内容。
(4)创建目录或文件 当创建一个目录时,文件系统会为该目录分配一个inode和至少一个block。该inode记录该目录的属性,并指向那块block。该block记录该目录下相关联的文件或目录的关联性和名字。 当创建一个文件时,文件系统会为该文件分配至少一个inode和与该文件大小相对应的数量的block。该inode记录该文件的属性,并指向block。 如果一个目录中的文件数太多,以至于1个block容纳不下这么多文件时,Linux的文件系统会为该目录分配更多的block。 (各block之间形成链表?)
(5)读取目录或文件 当我们告知操作系统一个文件的路径后,操作系统是如何找到这个文件的呢?首先操作系统会调用文件系统的相应接口,接下来: 递归说法:当读取一个文件或目录X时,提供给文件系统的是一个路径P。文件系统会先读取X所在的目录D的inode_d(注意这里,其实是这一操作的递归过程),通过inode_d获得其对应的block_d,在block_d中通过已知的X的名称,查询到X的inode_x。 迭代说法;如果读取的是/x1/x2/x3/x4/x5这个文件,则先读取根目录的inode_root,然后找到inode_root对应的block_root,在block_root中根据x1这个名字找到x1对应的inode_x1,然后找到inode_x1对应的block_x1,在block_x1中根据x2这个名字找到inode_x2,再找到block_x2,然后根据x3找到inode_x3,再block_x3,根据x4找到inode_x4,再block_x4,再根据x5找到inode_x5,再block_x5,就读取到我们要的x5的内容了。
2、分区(1)分区结构 分区(partition)在被Linux的文件系统(比如ext2)格式化的时候,会分成inode table和block table两部分,且大小都是固定的。该分区的所有inode都在inode table里,所有block都在block table里。
(2)块大小 ext2允许的block size为1024bytes、2048bytes和4096bytes。
(3)inode大小 ext2一般默认给inode预设的大小为128bytes。
(4)预设分区 一个T bytes的分区,设定每个block为B bytes,每个inode为I bytes。如果假设平均每个文件占用两个block的话,那么inode的数量就应该设定为T/(2B+I)个,即inode table为T*I/(2B+I) bytes,block table为T*B/(2B+I) bytes。所以一个分区的文件系统所能容纳的文件数量,被限制于该分区的文件系统的inode area中的inode数。 如果一个分区大小为1GB,每个block为4KB,一个inode为128B,并假设平均每个文件占用2个block。那么inode的数量为1GB/(8KB+128B)=129055.5,即129055。那么inode table的大小为129055*128B=15.75MB。所以按照这样的规划,如果一个1GB的磁盘,那么格式化后,就已经有15.75MB被使用了。 大文件应用场景:block设置的小一些,inode设置的多一些。比如新闻组、BBS等。 小文件应用场景:block设置的大一些,inode设置的少一些。比如图片分享网站。
3、查看本机的文件系统信息 使用dumpe2fs命令可以查看分区的文件系统的相关信息。比如我在我的一台测试机上查看sda1,可以输入:dumpe2fs /dev/sda1
会得到如下内容,一些信息已经标注在注释里了。
(1)文件系统基本信息
#该分区的文件系统的名称Filesystem volumn name: MAIN
#上次的挂载点Last mounted on: <not available>
#文件系统的通用唯一标识符Filesystem UUID: <none>
#文件系统的Filesystem magic number: 0xEF53
#修订版本号Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal needs_recoveryFilesystem flags: signed_directory_hashDefault mount options: (none)
#文件系统状态Filesystem state: clean
#发生错误后的行为Errors behavior: Continue
#操作系统Filesystem OS type: Linux
(2)结构信息
#Inode总数Inode count: 1313312
#Block总数Block count: 1313305
#保留block数Reserved block count: 65665
#空闲block数Free blocks: 979164
#空闲inode数Free inodes: 1298415
#第一个block的编号First block: 0
#block的大小Block size: 4096
#fragment的大小Fragment size: 4096
#每个group的block数是32K个Blocks per group: 32768
#每个group的fragment数是32K个Fragments per group: 32768
#每个group的inode数Inodes per group: 32032
#每个group的inode blocksInode blocks per group: 1001
(3)访问信息
#上次挂载时间Last mount time: Wed Jan 25 00:32:14 2012
#上次写时间Last write time: Wed Jan 24 00:32:14 2012
#挂载数Mount count: 11
#最大挂在数Maximum mount count: 20
#上次检查文件系统时间Last checked: Sat Oct 31 22:52:33 2009
#检查文件系统时间间隔Check intervalle: 15552000 (6 months)
#下一次检查文件系统的时间Next check after: Thu Apr 29 22:52:33 2010
#对保留块有权限的用户IDReserved blocks uid: 0 (user root)
#对保留快有权限的组IDReserved blocks gid: 0 (group root)
#第一个inodeFirst inode: 11
#每个inode大小Inode size:128
#日志inodeJournal inode: 8
#日志大小为32MJournal size: 32M
(4)group信息 Group 0: (Blocks 0-32767) Primary superblock at 0,Group descriptors at 1-1 Block bitmap at 2 (+2), Inode bitmap at 3 (+3) Inode table at 4-1004 (+4) 0 free blocks, 32019 free inodes, 2 directories Free blocks: Free inodes: 14-32032Group 1: (Blocks 32768-65535) Backup superblock at 32768, Group descriptors at 32769-32769 Block bitmap at 32770 (+2), Inode bitmap at 32771 (+3) Inode table at 32772-33772 (+4) 3 free blocks, 32032 free inodes, 0 directories Free blocks: 33773-33775 Free inodes: 32033-64064Group 2: (Blocks 65536-98303) Backup superblock at 65536, Group descriptors at 65537-65537 Block bitmap at 65538 (+2), Inode bitmap at 65539 (+3) Inode table at 65540-66540 (+4) 3 free blocks, 32032 free inodes, 0 directories Free blocks: 66541-66543 Free inodes: 64065-96096Group 3: (Blocks 98304-131071) Backup superblock at 98304, Group descriptors at 98305-98305 Block bitmap at 98306 (+2), Inode bitmap at 98307 (+3) Inode table at 98308-99308 (+4) 3 free blocks, 32031 free inodes, 0 directories Free blocks: 99309-99311 Free inodes: 96098-128128Group 4: (Blocks 131072-163839) Backup superblock at 131072, Group descriptors at 131073-131073 Block bitmap at 131074 (+2), Inode bitmap at 131075 (+3) Inode table at 131076-132076 (+4) 0 free blocks, 32032 free inodes, 0 directories Free blocks: Free inodes: 128129-160160...Group 40: (Blocks 1310720-1313304) Backup superblock at 1310720, Group descriptors at 1310721-1310721 Block bitmap at 1310722 (+2), Inode bitmap at 1310723 (+3) Inode table at 1310724-1311724 (+4) 1580 free blocks, 32032 free inodes, 0 directories Free blocks: 1311725-1313304 Free inodes: 1281281-1313312
可见,各Group对应的blocks(注意每个block的大小是4096bytes) - Group 00: 0(0x000000) - 32767(0x007FFF): 0K = 0 * 32K - Group 01: 32768(0x008000) - 65535(0x00FFFF): 32K = 1 * 32K - Group 02: 65536(0x010000) - 98303(0x017FFF): 64K = 2 * 32K - Group 03: 98304(0x018000) - 131071(0x01FFFF): 96K = 3 * 32K - Group 04: 131072(0x020000) - 163839(0x027FFF): 128K = 4 * 32K … - Group 40: 1310720(0x140000) - 1313304(0x147FFF): 1280K = 40 * 32K
这40个group一共的大小,是40*32K*4KB = 5GB
4、文件系统结构 结合上面命令的输出结果,一个分区一般含有多个block group,比如上面看到的40个。而每个block group都有superblock、group description、block bitmap、inode bitmap、inode table、data blocks,比如上面的Backup Superblock占用1个block(4KB)、Group descriptors占用1个block(4KB)、Block bitmap占用1个block(1KB)、Inode bitmap占用1个block(1KB)、Inode table占用1001个block(512.5KB)。 Superblock记录整个partition的block和inode的总量,已使用和未使用的inode和block的数量,1个block和1个inode的大小,filesystem的挂载时间/最后写入时间/最后检查时间、标示该文件系统是否被挂载的valid bit(0标示未挂载,1标示已挂载)。是MBR中的Superblock的backup。 Group descriptors描述由何处开始记录数据,是MBR中的Group descriptors的backup。 Block bitmap记录哪个block是空闲的。 Inode bitmap记录哪个inode是空闲的。 Inode table存放inode数据。 Data blocks存放block数据。
2、Superblock
1、首先了解下block,对于ext2(ext3)文件系统而言,硬盘分区首先被划分为一个个的block,同一个ext2文件系统上的每个block大小都是一样的。但是对于不同的ext2文件系统,block的大小可以有区别。典型的block大小是1024 bytes或者4096 bytes。这个大小在创建ext2、ext3文件系统的时候被决定,mkfs –t ext2/3 –b xx就可以设定块大小了!一个硬盘分区上的block计数是从0开始的,总的来说,block这个概念好理解。
2、理解了block的概念后,接着就是对block group的理解,硬盘分区上所有的block被聚在一起分成几个大的block group。其中每个block group中有多少个block是固定的。从上面的图可以看出来!每个block group都相对应一个group descriptor,每个group descriptor当中有几个重要的block指针,指向block group中的inode table、block bitmap和inode bitmap。以上三个结构记载了其所属block group的许多信息。
3、下面就是对super block的理解了 Super block即为超级块,它是硬盘分区开头——开头的第一个byte是byte 0,从 byte 1024开始往后的一部分数据。由于 block size最小是 1024 bytes,所以super block可能是在block 1中(此时block 的大小正好是 1024 bytes) 超级块中的数据其实就是文件卷的控制信息部分,也可以说它是卷资源表,有关文件卷的大部分信息都保存在这里。例如:硬盘分区中每个block的大小、硬盘分区上一共有多少个block group、以及每个block group中有多少个inode。 对于super block的结构和涵义可以通过查看/usr/include/linux/ext3_fs.h文件:
Superblock 是文件系统最基本的元数据,它定义了文件系统的类似、大小、状态,和其他元数据结构的信息(元数据的元数据)。Superblock 对于文件系统来说是非常关键的,因此对于每个文件系统它都冗余存储了多份。Superblock对于文件系统来说是一个非常“高等级”的元数据结构。例如,如果 /var 分区的 Superblock 损坏了,那么 /var 分区将无法挂载。在这时候,一般会执行 fsck 来自动选择一份 Superblock 备份来替换损坏的 Superblock,并尝试修复文件系统。
主 Superblock 存储在分区的 block 0 或者 block 1 中,而 Superblock 的备份则分散存储在文件系统的多组 block 中。当需要手工恢复时,我们可以使用
dumpe2fs /dev/sda1 | grep -i superblock 来查看 sda1 分区的 superblock 备份有哪一份是可用的。我们假设 dumpe2fs 输出了这样一行:
Backup superblock at 163840, Group descriptors at 163841-163841 ,
通过这条信息,我们就可以尝试使用这个 superblock 备份:
/sbin/fsck.ext3 -b 163840 -B 1024/dev/sda1。请注意,这里我们假设 block 的大小为 1024 字节。
通过set number:386 struct ext3_super_block {386 struct ext3_super_block {387 /*00*/ __le32 s_inodes_count; /* Inodes count */388 __le32 s_blocks_count; /* Blocks count */389 __le32 s_r_blocks_count; /* Reserved blocks count */390 __le32 s_free_blocks_count; /* Free blocks count */391 /*10*/ __le32 s_free_inodes_count; /* Free inodes count */392 __le32 s_first_data_block; /* First Data Block */393 __le32 s_log_block_size; /* Block size */394 __le32 s_log_frag_size; /* Fragment size */395 /*20*/ __le32 s_blocks_per_group; /* # Blocks per group */396 __le32 s_frags_per_group; /* # Fragments per group */397 __le32 s_inodes_per_group; /* # Inodes per group */398 __le32 s_mtime; /* Mount time */399 /*30*/ __le32 s_wtime; /* Write time */400 __le16 s_mnt_count; /* Mount count */401 __le16 s_max_mnt_count; /* Maximal mount count */402 __le16 s_magic; /* Magic signature */403 __le16 s_state; /* File system state */404 __le16 s_errors; /* Behaviour when detecting errors */405 __le16 s_minor_rev_level; /* minor revision level */406 /*40*/ __le32 s_lastcheck; /* time of last check */407 __le32 s_checkinterval; /* max. time between checks */408 __le32 s_creator_os; /* OS */409 __le32 s_rev_level; /* Revision level */410 /*50*/ __le16 s_def_resuid; /* Default uid for reserved blocks */411 __le16 s_def_resgid; /* Default gid for reserved blocks */
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。相关文章推荐
- Linux 文件系统的 Superblock, Inode, Dentry 和 File
- Linux 文件系统(一)---虚拟文件系统VFS----超级块、inode、dentry、file
- Linux 文件系统(一)---虚拟文件系统VFS----超级块、inode、dentry、file
- Linux 文件系统(一)---虚拟文件系统VFS----超级块、inode、dentry、file
- Linux 文件系统(一)---虚拟文件系统VFS----超级块、inode、dentry、file
- 关于VFS文件系统中的superblock、inode、d_entry和file数据结构
- 文件系统VFS数据结构(超级块 inode dentry file)(收集整理)
- linux文件系统的系统分析--(八)sysfs中sysfs_dirent与inode dentry的关系
- Linux/Unix inode、vnode、dentry、file、进程表、文件表(中)
- Linux/Unix inode、vnode、dentry、file、进程表、文件表(下)
- Linux文件系统基础之inode和dentry
- 文件系统系列学习笔记 - inode/dentry/file/super(2)
- Linux文件系统之inode、dentry
- linux文件系统的系统分析--(八)sysfs中sysfs_dirent与inode dentry的关系
- Linux/Unix inode、vnode、dentry、file、进程表、文件表(上)
- linux驱动学习--第九天:第五章 Linux 文件系统与设备文件系统(三) 之 file 结构体 和 inode 结构体
- Linux 文件系统层次结构标准简介(Filesystem Hierarchy Standard)
- linux文件系统类型How do I identify my file system type?
- 根inode腐败在Linux上运行fsck将在挂载文件系统后