ext2文件系统
- ext2文件系统全称是
second extended file system
。最大的文件大小是2T.最大文件系统的大小上限是32TB.目录允许的最大的子目录数为32000个。ext2的限制相对较多,对于现在很多应用来说ext2并非是首选。 - ext2文件系统中的目录项是由
struct ext2_dir_entry_2
呈现,目录项中存储inode和对应文件或者目录名称,结构如下图所示
// 文件名称或者目录名称的最大长度,在内核中已经限定了
#define EXT2_NAME_LEN 255
// ext2文件系统新版目录项定义
struct ext2_dir_entry_2 {
// 文件或者目录项的inoide
__le32 inode;
// 目录项在磁盘占用的大小,当删除目录项时候重置inode
__le16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[]; /* File name, up to EXT2_NAME_LEN */
};
- ext2文件系统基本的物理存储单元是以
block
为基本单位,block
大小已经在文件系统实现中定义了最大和最小 block大小。具体如下:
// 定义最小block大小,单位是字节
#define EXT2_MIN_BLOCK_SIZE 1024
// 定义最大的block大小
#define EXT2_MAX_BLOCK_SIZE 4096
- ext2文件系统在磁盘上是由很多的
block group
组成,每个block group
包含了super block
、block group descriptor
、block bitmap
、inode bitmap
、inode table
、data blocks
几大块组成。super block
在每个block group中具有相同的内容,具体参考如下
- ext2文件系统文件访问采用直接和间接的block来访问,对于大文件的访问非常不友好,如下是一个文件访问的示例
ext3文件系统
- ext3文件系统允许journaling日志,journaling日志是在文件系单独的区域存储,每当文件系统意外崩溃,采用journaling日志可以进行恢复。ext3文件系统允许的最大文件是2T。整个文件系统的大小限制是32T。和ext2文件系统不同的是多出了journaling日志的功能
- ext3的journal能够保证文件系统的一致性和恢复时间。当服务器意外宕机,宕机时候ext3文件系统并没有umount,当服务器启动后,在mount前会检查文件系统完整性,文件系统所在的磁盘空间越大,花费的时间就越长。开启了ext3文件系统的
has_journal
选型,一致性检查会去重放日志,这个操作就非常快。ext3文件系统中任何的操作都会记录在journal日志中.journal是一个固定大小,循环的数组内存空间,journal存储在磁盘是以特殊文件通过硬链接实现。journal功能核心是transaction
和checkpoint
技术实现,transaction
是针对每个文件系统的更改是一个单独事务,事务定期提交到磁盘,事务一旦提交到磁盘,日志的内存区域可以重复使用;checkpoint
是当达到某些边界条件会触发事务提交到磁盘。每个journal是由begin marker
、log
、end marker
组成,具体如下图
- ext3提供三种journal日志模式,分别是
writeback
、ordered
、journal
.writeback
仅仅会记录元数据的日志,数据可以直接写到磁盘,但是不保证数据比元数据先落盘,这也是性能最好的,但是数据安全性最低;ordered
也是仅仅是记录元数据块的日志,这种模式是将文件的数据相关的元数据和数据在一个事务中,当元数据写入到磁盘时候,把对应的数据也写到磁盘,这样是先数据刷盘,再做元数据日志。journal
提供数据和元数据的日志,所有的文件数据都先写到日志,然后在写到磁盘,数据需要写2次,性能是最差的。 - ext2中在目录项中查找文件时间的复杂度是
O(n)
,ext3中采用了h-trees
查找效率提高了很多。
struct dx_root
{
struct fake_dirent dot;
char dot_name[4];
struct fake_dirent dotdot;
char dotdot_name[4];
struct dx_root_info
{
__le32 reserved_zero;
u8 hash_version;
u8 info_length; /* 8 */
u8 indirect_levels;
u8 unused_flags;
}
info;
struct dx_entry entries[0];
};
struct dx_entry
{
__le32 hash;
__le32 block;
};
struct fake_dirent
{
__le32 inode;
__le16 rec_len;
u8 name_len;
u8 file_type;
};
ext4文件系统
- ext4是从ext3 fork而来,但是增加了很多特性。支持最大文件大小是16TB.文件系统大小的最大限制是1EB。每个目录可以包含64000个子目录。同时增加了
multiple block allocation
、delayed allocation
、journal checksum
、fast fsck
等非常有价值的功能。提供关闭journal
功能的开关。ext4的inode默认大小是256个字节。 - 针对ext4最大的feature就是ext4采用
extents
机制,替代了indirect block
寻址的方式。ext4尽量会把数据存储在连续的block区域内,为了实现这个ext4需要知道三个信息,第一是文件的初始化block.其次是块的数量,最后是磁盘上初始化块的数据,这些信息统一抽象以struct ext4_extent
呈现。extent
在默认的block=4K情况下,extent大小是128MB
// ext4最小block大小是1K
#define EXT4_MIN_BLOCK_SIZE 1024
// ext4最大的block大小是64K
#define EXT4_MAX_BLOCK_SIZE 65536
// 文件连续存储需要的基本信息统一是以ext4_extent呈现
struct ext4_extent {
__le32 ee_block; /* first logical block extent covers */
__le16 ee_len; /* number of blocks covered by extent */
__le16 ee_start_hi; /* high 16 bits of physical block */
__le32 ee_start_lo; /* low 32 bits of physical block */
};
/*
* This is index on-disk structure.
* It's used at all the levels except the bottom.
*/
struct ext4_extent_idx {
__le32 ei_block; /* index covers logical blocks from 'block' */
__le32 ei_leaf_lo; /* pointer to the physical block of the next *
* level. leaf or next index could be there */
__le16 ei_leaf_hi; /* high 16 bits of physical block */
__u16 ei_unused;
};
/*
* Each block (leaves and indexes), even inode-stored has header.
*/
struct ext4_extent_header {
__le16 eh_magic; /* probably will support different formats */
__le16 eh_entries; /* number of valid entries */
__le16 eh_max; /* capacity of store in entries */
__le16 eh_depth; /* has tree real underlying blocks? */
__le32 eh_generation; /* generation of the tree */
};
以存储512M文件为例,展示了ext4_extent、ext4_extent_idx、ext4_extent_header
之间的关系
multiple block allocation
机制保证了文件存储能够在extent的连续block空间内,对于大文件存储效率非常高,同时也会缩短文件seek的时间。、delayed allocation
机制能够在文件写入的时候不直接申请block,而是当文件flush到磁盘时候在去申请block进行存储,这样可以减少数据碎片,提高存储效率。