文件系统是操作系统的一个重要组成部分,也有着举足轻重的地位。本系列文章主要讲述了linux ext4文件系统的一些实现原理。笔者参考了2.6.32.60的内核源代码。在写这篇的文章时,最新的内核已经去到了3.7.9。
ext4是替代ext2/3的Linux文件系统。从2.6.28版本开始,被正式认定进入稳定(stable)。本文主要介绍ext4文件系统在硬盘层面上的存储结构及原理。
读者对象:对Linux有一定基础,希望了解ext4底层原理,和它与ext2/3系统区别。
关键词汇
先回顾几个基本的概念,如果不是特别清楚下面几个概念的话,可以去google一下。
inode:索引节点
superblock:超级块
block:文件系统块
block group:文件系统块组
disk block:磁盘块(512字节)
block device:块设备
VFS:虚拟文件系统
EXT4存储结构
假如把整个超级块比如一本书,那么文件系统的工作就是把要记录的内容,按页码,行段记录在这本书里。这当然也包括书的目录了。我们使用dumpe2fs工具输出:
Reserved GDT blocks: 609 Blocks per group: 32768 Fragments per group: 32768 Inodes per group: 8128 Inode blocks per group: 508 Flex block group size: 16 Filesystem created: Mon May 14 13:30:51 2012 Last mount time: Sun Jan 6 18:51:16 2013 Last write time: Sun Jan 6 18:51:16 2013 Mount count: 282 Maximum mount count: -1 Last checked: Mon May 14 13:30:51 2012 Check interval: 0 (<none>) Lifetime writes: 20 GB Reserved blocks uid: 0 (user root) Reserved blocks gid: 0 (group root) First inode: 11 Inode size: 256 Required extra isize: 28 Desired extra isize: 28 Journal inode: 8 |
首先,映入眼帘的是该超级块的相关重要参数,比如inode大小,块组含块数,块组inode数目等等。这些数据是存在ext4_super_block,ext4_sb_info这两个结构体中,定义在ext4.h头文件里,它们不是本篇重要讨论的内容。我们只需要知道它们是存放一些超级块信息的结构体即可。
接下来,可以看到ext4硬盘上的存储结构:
Group 0: (Blocks 0-32767) [ITABLE_ZEROED] Checksum 0x7cf3, unused inodes 0 Primary superblock at 0, Group descriptors at 1-2 Reserved GDT blocks at 3-611 Block bitmap at 612 (+612), Inode bitmap at 628 (+628) Inode table at 644-1151 (+644) 2720 free blocks, 0 free inodes, 1383 directories Free blocks: 8888-8959, 9068, 9071-9135, 9144-9175, 9200-9207, 9213-9214, 9279, 9700-10120, 11823-11964, 12213-12870, 12879-13043, 13139-13254, 18432-19021, 22748-22975, 32549-32767 Free inodes: |
这是块组0的情况,它表明块组0由块号为0-32767这32768个块组成,超级块基本信息存在块0,块组描述符在块1-2,预留的块组描述符表在块3-611,块位图在块612中,inode位图在块628中,Inode表在块644-1151中,空闲的块有很多,空闲的inode没了。
接下来,我们将重点分析这句废话中每个词的含义
超级块基本信息:
我们在前面已经讲过了。顾名思义,不多解释。
块组描述符
在内核中就是结构体ext4_group_desc,它包括的内容为:块位图块号,inode位图块号,inode表块号,空闲块计数,自由块计数等等。
预留的块组描述符表
为以后要使用所留下来的空间。
块位图
这个就是一个块使用情况记录表。记录哪些块使用,哪些块未使用。它的原理就是对整个块组中0-32767这总共32768个块中作一个映射。根据一个bytes有8个位00000000,一个块有4096bytes也就是有4096*8=32768个位,这32768个位刚好对应了块组中32768的块。如果第N个块被使用了则标记第N位为1,否则为0。