1、ext2产生的历史

  最早的Linux内核是从MINIX系统过渡发展而来的。Linux最早的文件系统就是MINIX文件系统。MINIX文件系统几乎到处都是bug,采用的是16bit偏移量,最大容量为64M,文件名最长为14字符。
  Linux内核0.96版本,包含了虚拟文件系统(vitual file system, VFS),VFS中提供了基础的API用于简化扩展新的文件系统——扩展的文件系统(extended file system, ext)基于VFS API。
  1992年Linux发布的0.96内核版本拥有了Linux真正意义上的文件系统——扩展的文件系统(The Extended Filesystem, ext),ext采用虚拟文件系统(virtual file system, VFS)即基础的API接口简化扩展的文件系统添加于内核。ext使得单个文件的最大数据容量可达2G,文件名的最大长度扩展到了255个字符。但是ext中不支持文件访问atime,文件内容修改mtime,文件属性修改iNode中的ctime相互独立的时间戳。
  为了解决文件的时间戳问题,1993年Linux 0.99版本内核推出,Linux推出了两种新的文件系统:xiafs和ext2(The Second Extended Filesystem).ext2的许多设计理念与Berkeley Fast File System相同,具有扩展的理念,在磁盘数据结构中预留了扩展空间,给将来的新版文件系统的留下了扩展空间。
  之后,ext2成了VFS API中许多新扩展的测试平台。例如VFS内含的POSIX访问控制协议草案和扩展属性协议最先内嵌于ext2,归功于ext2的易扩展和易于理解的中断机制。到了Linux的2.6.17内核版本,ext2中的文件最大可达2TB。目前,ext2在闪盘和固态硬盘领域其影响仍由于日志文件系统(ext3/ext4)。因为ext2没有ext3那样额外的日志写操作。因为频繁的写操作,会降低磁盘的使用寿命,相反固态硬盘的寿命因此得以延长。闪盘因为在挂载的时候没有访问时间戳atime,寿命也得意延长。

翻译自维基百科:https://en.wikipedia.org/wiki/Ext2

2、ext2文件系统的结构

在磁盘中,ext2文件系统的结构可以用以下图来描述:

注意:以上是一个磁盘分区,第一个block,是系统启动扇区(boot sector),其余的分区空间都给了ext2文件系统,ext2将该磁盘分区分成了若干个块组(block group 0-N)。

以下是ext2数据结构(ext2_fs.h):

         /*
2 * linux/include/linux/ext2_fs.h
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/include/linux/minix_fs.h
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 */ #ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H #include <linux/types.h> /*
22 * The second extended filesystem constants/structures
23 */ /*
26 * Define EXT2FS_DEBUG to produce debug messages
27 */
#undef EXT2FS_DEBUG /*
31 * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
32 */
#define EXT2_PREALLOCATE
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 /*
37 * The second extended file system version
38 */
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b" /*
43 * Debug code
44 */
#ifdef EXT2FS_DEBUG
# define ext2_debug(f, a...) { \
printk ("EXT2-fs DEBUG (%s, %d): %s:", \
__FILE__, __LINE__, __FUNCTION__); \
printk (f, ## a); \
}
#else
# define ext2_debug(f, a...) /**/
#endif /*
56 * Special inode numbers
57 */
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ /* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11 /*
69 * The second extended file system magic number
70 */
#define EXT2_SUPER_MAGIC 0xEF53 /*
74 * Maximal count of links to a file
75 */
#define EXT2_LINK_MAX 32000 /*
79 * Macro-instructions used to manage several block sizes
80 */
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + )
#endif
#ifdef __KERNEL__
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
#else
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : \
(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
#endif /*
110 * Macro-instructions used to manage fragments
111 */
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
#else
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
#endif /*
124 * ACL structures
125 */
struct ext2_acl_header /* Header of Access Control Lists */
{
__u32 aclh_size;
__u32 aclh_file_count;
__u32 aclh_acle_count;
__u32 aclh_first_acle;
}; struct ext2_acl_entry /* Access Control List Entry */
{
__u32 acle_size;
__u16 acle_perms; /* Access permissions */
__u16 acle_type; /* Type of entry */
__u16 acle_tag; /* User or group identity */
__u16 acle_pad1;
__u32 acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
}; /*
146 * Structure of a blocks group descriptor
147 */
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[];
}; /*
161 * Macro-instructions used to manage group descriptors
162 */
#ifdef __KERNEL__
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
#else
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
#endif /*
175 * Constants relative to the data blocks
176 */
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) /*
184 * Inode flags
185 */
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ #define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ /*
207 * ioctl commands
208 */
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
#define EXT2_IOC_SETVERSION _IOW('v', 2, long) /*
215 * Structure of an inode on the disk
216 */
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[];
} masix2;
} osd2; /* OS dependent 2 */
}; #define i_size_high i_dir_acl #if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_uid_low i_uid
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#define i_reserved2 osd2.linux2.l_i_reserved2
#endif #ifdef __hurd__
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#endif #ifdef __masix__
#define i_reserved1 osd1.masix1.m_i_reserved1
#define i_frag osd2.masix2.m_i_frag
#define i_fsize osd2.masix2.m_i_fsize
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif /*
301 * File system states
302 */
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
#define EXT2_ERROR_FS 0x0002 /* Errors detected */ /*
307 * Mount flags
308 */
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/*
323 * Maximal mount counts between two filesystem checks
324 */
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ /*
329 * Behaviour when detecting errors
330 */
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE /*
337 * Structure of the super block
338 */
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
366 * These fields are for EXT2_DYNAMIC_REV superblocks only.
367 *
368 * Note: the difference between the compatible feature set and
369 * the incompatible feature set is that if there is a bit set
370 * in the incompatible feature set that the kernel doesn't
371 * know about, it should refuse to mount the filesystem.
372 *
373 * e2fsck's requirements are more strict; if it doesn't know
374 * about a feature in either the compatible or incompatible
375 * feature set, it must abort and not try to meddle with
376 * things it doesn't understand...
377 */
__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 */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[]; /* 128-bit uuid for volume */
char s_volume_name[]; /* volume name */
char s_last_mounted[]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
389 * Performance hints. Directory preallocation should only
390 * happen if the EXT2_COMPAT_PREALLOC flag is on.
391 */
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u32 s_reserved[]; /* Padding to the end of the block */
}; #ifdef __KERNEL__
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
#else
/* Assume that user mode programs are passing in an ext2fs superblock, not
402 * a kernel struct super_block. This will allow us to call the feature-test
403 * macros from user land. */
#define EXT2_SB(sb) (sb)
#endif /*
408 * Codes for operating systems
409 */
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4 /*
417 * Revision levels
418 */
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ #define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV #define EXT2_GOOD_OLD_INODE_SIZE 128 /*
428 * Feature set definitions
429 */ #define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
#define EXT2_SET_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
#define EXT2_SET_INCOMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask) #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT2_FEATURE_COMPAT_ANY 0xffffffff #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT2_FEATURE_RO_COMPAT_ANY 0xffffffff #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff #define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP /*
478 * Default values for user and/or group using reserved blocks
479 */
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0 /*
484 * Structure of a directory entry
485 */
#define EXT2_NAME_LEN 255 struct ext2_dir_entry {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u16 name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
}; /*
496 * The new version of the directory entry. Since EXT2 structures are
497 * stored in intel byte order, and the name_len field could never be
498 * bigger than 255 chars, it's safe to reclaim the extra byte for the
499 * file_type field.
500 */
struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
}; /*
510 * Ext2 directory file types. Only the low 3 bits are used. The
511 * other bits are reserved for now.
512 */
enum {
EXT2_FT_UNKNOWN,
EXT2_FT_REG_FILE,
EXT2_FT_DIR,
EXT2_FT_CHRDEV,
EXT2_FT_BLKDEV,
EXT2_FT_FIFO,
EXT2_FT_SOCK,
EXT2_FT_SYMLINK,
EXT2_FT_MAX
}; /*
526 * EXT2_DIR_PAD defines the directory entries boundaries
527 *
528 * NOTE: It must be a multiple of 4
529 */
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND) #ifdef __KERNEL__
/*
537 * Function prototypes
538 */ /*
541 * Ok, these declarations are also in <linux/kernel.h> but none of the
542 * ext2 source programs needs to include it so they are duplicated here.
543 */
# define NORET_TYPE /**/
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn, /* balloc.c */
extern int ext2_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
extern int ext2_new_block (struct inode *, unsigned long,
__u32 *, __u32 *, int *);
extern void ext2_free_blocks (struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
extern void ext2_check_blocks_bitmap (struct super_block *);
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh); /* dir.c */
extern int ext2_add_link (struct dentry *, struct inode *);
extern ino_t ext2_inode_by_name(struct inode *, struct dentry *);
extern int ext2_make_empty(struct inode *, struct inode *);
extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct dentry *, struct page **);
extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
extern int ext2_empty_dir (struct inode *);
extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *); /* fsync.c */
extern int ext2_sync_file (struct file *, struct dentry *, int);
extern int ext2_fsync_inode (struct inode *, int); /* ialloc.c */
extern struct inode * ext2_new_inode (const struct inode *, int);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
extern unsigned long ext2_count_free (struct buffer_head *, unsigned); /* inode.c */
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *, int);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
extern void ext2_truncate (struct inode *); /* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
unsigned long); /* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, , )));
extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
const char *, ...)
__attribute__ ((NORET_AND format (printf, , )));
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, , )));
extern void ext2_update_dynamic_rev (struct super_block *sb);
extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int ext2_statfs (struct super_block *, struct statfs *); /*
611 * Inodes and files operations
612 */ /* dir.c */
extern struct file_operations ext2_dir_operations; /* file.c */
extern struct inode_operations ext2_file_inode_operations;
extern struct file_operations ext2_file_operations; /* inode.c */
extern struct address_space_operations ext2_aops; /* namei.c */
extern struct inode_operations ext2_dir_inode_operations; /* symlink.c */
extern struct inode_operations ext2_fast_symlink_inode_operations; #endif /* __KERNEL__ */ #endif /* _LINUX_EXT2_FS_H */

ext2_fs.h

2.1 超级块(Super Blook)

超级块的数据结构如下:

       /*
337 * Structure of the super block
338 */
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
366 * These fields are for EXT2_DYNAMIC_REV superblocks only.
367 *
368 * Note: the difference between the compatible feature set and
369 * the incompatible feature set is that if there is a bit set
370 * in the incompatible feature set that the kernel doesn't
371 * know about, it should refuse to mount the filesystem.
372 *
373 * e2fsck's requirements are more strict; if it doesn't know
374 * about a feature in either the compatible or incompatible
375 * feature set, it must abort and not try to meddle with
376 * things it doesn't understand...
377 */
__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 */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[]; /* 128-bit uuid for volume */
char s_volume_name[]; /* volume name */
char s_last_mounted[]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
389 * Performance hints. Directory preallocation should only
390 * happen if the EXT2_COMPAT_PREALLOC flag is on.
391 */
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u32 s_reserved[]; /* Padding to the end of the block */
};

struct ext2_super_block

主要的几项描述有:s_inodes_count / s_blocks_count(该分区inode/block总数),s_free_inodes_count / s_free_blocks_count(该分区空闲inode/block数),s_first_data_block(数据块中的起始块位置),s_log_block_size(块大小),s_blocks_per_group(每个块组的块数),s_magic(魔数)

struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
...
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
...
__u32 s_blocks_per_group; /* # Blocks per group */
...
__u16 s_magic; /* Magic signature */ # ext2的魔数为0xEF53
...

说明:每个块组中都有一份超级块的拷贝。当文件系统挂载时,通常只有块组0中的超级块(主备份)会被读取,其他的块组中的超级块只是作为备份,以防文件系统的崩溃。

2.2 组描述符表(Group Descriptors Table,GDT)

超级块之后就是组描述符表,是由该分区所有的块的组描述符(Group Descriptor)组成的,每个块组描述符记录了本块组的inode/block bitmap和inode table等。块组描述符数据结构如下所示:

struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};

说明:与超级类似,组描述符表也存在各块组中紧接着超级块,其目的与超级块一样,作为备份,防止文件系统的崩溃。

2.3 块位图和inode位图(block/inode bitmap)

位图(bitmap)是位(bit)的序列,每一个位代表该位图所在块组中的一个特定的数据块(block bitmap)或inode table中一个特定的inode(inode bitmap)。当bit为0时,表示对应的block/inode空闲;为1时,表示已被占用。

位图始终索引其所在的块组,并且block位图和inode位图均为1block大小,从而限制了该块组的大小。例如一般的block大小为1024bytes,因此一个块组总共有1024*8个block。

2.4 inode表(inode table)

inode表由一系列连续的block块组成,每个块中都预定义了一定数量的inode。inode表的起始块位置(块号)存储在组描述符的bg_inode_table字段中。

系统对inode表中的inode进行编号,从1开始,inode的数据结构被定义在ext2_fs.h文件的struct ext2_inode函数中:

       /*
215 * Structure of an inode on the disk
216 */
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[];
} masix2;
} osd2; /* OS dependent 2 */
};

struct ext2_inode

以下是inode数据结构中比较重要的字段:

struct ext2_inode {
__u16 i_mode; /* File type and access rights */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
...
__u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */
...
};

i_mode字段中包含了文件的类型和文件的访问权限,被定义在宏文件macro (sys/stat.h)中。

Sign Type Macro
- Regular file S_ISREG(m)
d Directory S_ISDIR(m)
c Character Device   S_ISCHR(m)
b Block Device S_ISBLK(m)
f Fifo S_ISIFO(m)
s Socket S_ISSOCK(m)
l Symbolic Link S_ISLNK(m)
Domain Read Write Exec All
User S_IRUSR S_IWUSR S_IXUSR S_IRWXU
Group S_IRGRP S_IWGRP S_IXGRP S_IRWXG
All S_IROTH S_IWOTH S_IXOTH S_IRWXO
 

i_blocks是该inode指向的文件已使用的block数量;指向数据块的指针存储于字段i_block[EXT2_N_BLOCKS]的数组结构中。

变量EXT2_N_BLOCKS定义在ext2_fs.h的第177行中:

   174	/*
175 * Constants relative to the data blocks
176 */
177 #define EXT2_NDIR_BLOCKS 12
178 #define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
179 #define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
180 #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
181 #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)

i_block[]数组中有15个指针,它们所代表的含义如下:

  • i_block[0..11] point directly to the first 12 data blocks of the file.              # 序列号0-11的12个元素(指针)指向文件开头的12个数据块
  • i_block[12] points to a single indirect block                                               # 第13号元素指向单索引间接块
  • i_block[13] points to a double indirect block                                              # 第14号元素指向双索引间接块
  • i_block[14] points to a triple indirect block                                                 # 第15号元素指向三索引间接块

由此我们可以计算出ext2文件系统单个文件的最大容量(假设block大小为1K),数组i_block[]的长度为32bit/8=4byte:

  • 直接索引:12 指针
  • 单间接索引:1024/4=256个直接索引,256 指针
  • 双间接索引:1024/4=256个单间接索引,256*256 指针
  • 三间接索引:1024/4=256个双间接索引,256*256*256 指针

因此可得到12K+256K+64M+16G,即大致为16G。如果block的大小为4K,则文件最大可为4T。(注意:真正决定文件大小的是底层的寄存器,寄存器的位数决定了其寻址的能力)

2.5 inode表中的inode指向的目录文件

inode指向的目录文件需加以注意,我们可以通过测试S_ISDIR(mode) macro来加以识别:

if (S_ISDIR(inode.i_mode)) ... 

假设inode指向的块是目录实体/home,目录中的内容包含了一系列的文件名和指向inode表中的对应的,如下图:

目录文件的数据结构如下:

struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};

字段file_type总共有0-7可能的值,分别代表: 

目录内容中的各项(实体)的大小是非固定的,大小取决于文件名称的长度。文件名称最大长度为EXT2_NAME_LEN的值,一般为255;文件名称的实际长度存放于字段name_len;rec_len存储的是本目录实体的大小,该字段自然也就决定了下一目录实体的位置了。

  Example of EXT2 directory

注意:目录中的inode号,指向的是inode表中的inode,指向data block的是i_block[EXT2_N_BLOCKS]的数组中的指针。

2.6 文件操作(创建、查找、修改、删除)的本质

http://cs.smith.edu/~nhowe/Teaching/csc262/oldlabs/ext2.html

https://www.cnblogs.com/f-ck-need-u/p/7016077.html

待完善...

Linux中ext2文件系统的结构的更多相关文章

  1. Linux 下EXT2文件系统 —— 如何将蚂蚁和大象优雅的装进冰箱里

    这一阵子真是偷懒,无时无刻不和自己身体中的懒癌做斗争.最终我还是被打败了,星期天两天几乎都是荒废过去的,在空闲的时候实际上我内心也是有点焦虑的,不知道去怎么度过这时间.学习吧又不想学习,看电视娱乐吧也 ...

  2. 文件系统的特性,linux的EXT2文件系统【转】

    本文转载自:https://blog.csdn.net/tongyijia/article/details/52809281 先来提出三个概念: - superblock - inode - bloc ...

  3. Linux中表示“时间”的结构体和相关函数

    转载于:http://blog.chinaunix.net/uid-25909722-id-2827364.html      Linux中表示“时间”的结构体和相关函数 2011-09-13 17: ...

  4. LInux中的文件系统1

    2017-03-08 10:37:55 一.虚拟文件系统VFS 文件系统用于将位于磁盘上的文件按照某种方式组织进内存,并给上层应用程序提供统一的访问接口.Linux支持多种文件系统EXT2/3,NTF ...

  5. Linux中进程控制块PCB-------task_struct结构体结构

    Linux中task_struct用来控制管理进程,结构如下: struct task_struct { //说明了该进程是否可以执行,还是可中断等信息 volatile long state; // ...

  6. Linux基本操作 2-----Linux文件系统基本结构

    Linux的文件系统结构             Linux文件系统为一个倒转的单根树状结构 文件系统的根为"/" 文件系统严格区分大小写 路径使用“/”来分割,在windows使 ...

  7. linux中proc文件系统 -- ldd3读书笔记

    1./proc 文件系统概述 /proc 文件系统是由软件创建,被内核用来向外界报告信息的一个文件系统./proc 下面的每一个文件都和一个内核函数相关联,当文件的被读取时,与之对应的内核函数用于产生 ...

  8. linux中查看文件夹结构的小工具

    tree命令是Linux/UNIX系统中常用的命令,可以非常方便地查看文件夹的结构,并且以树形目录的形式展示 在Ubuntu中安装 sudo apt-get install tree 在CentOS中 ...

  9. Linux中文件/文件系统的压缩、打包和备份总结(基于rhel7)

    文件/文件系统的压缩.打包 Linux有哪些压缩工具可供选择 按压缩比:xz>bzip2>gzip,按压缩时长:gzip>bzip2>xz,另外还有zip可以选择. gzip只 ...

随机推荐

  1. 【转】 Pro Android学习笔记(六十):Preferences(4):MultiSelect List Preference

    目录(?)[-] XML文件 在设备中保存 读出信息 ListPreference提供单选列表,我们可以通过CheckBoxPreference提供多选列表.此外,Android在3.0后提供Mult ...

  2. 进程vs线程

    内存中的内容不同 进程->{ 进程是系统分配资源的最基本单位,线程是进程的一部分, 进程中存储文件和网络句柄 } 线程->{ 栈(每个线程都有一个栈空间) pc(当前或下一条指令的地址,指 ...

  3. WEB服务器(IIS)的配置与管理

    安装Web服务器(IIS) 在"服务器管理器"-"角色"-"添加角色"-选择"Web服务器(IIS)"进行安装 这里,我 ...

  4. CentOS 7 配置 ISCSI 服务器

    一.服务器配置 1.安装配置软件: yum install targetcli -y 2.进入配置界面: targetcli ,并进行如下配置: 1) /backstores/block create ...

  5. LoadRunner 服务器(Linux、Windows) 性能指标度量说明

    服务器资源性能计数器 下表描述了可用的计数器: 监控器 度量 说明 CPU 监控器 Utilization 监测 CPU 利用率. 磁盘空间监控器 Disk space 监测可用空间 (MB) 和已用 ...

  6. linux docket

    什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于  ...

  7. LeetCode第14题:最长公共前缀

    题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...

  8. Django 之 logging

    1. logging 1.1 什么是 logging logging 模块是 Python 内置的日志管理模块,不需要额外安装. 使用: import logging logging.critical ...

  9. 【Spring-任务调度】

    Spring-任务调度: spring内部有一个task是Spring自带的一个设定时间自动任务调度task使用的时候很方便,但是他能做的东西不如quartz那么的多!可以使用注解和配置两种方式,配置 ...

  10. js原生实现轮播图效果(面向对象编程)

    面向对象编程js原生实现轮播图效果 1.先看效果图 2.需要实现的功能: 自动轮播 点击左右箭头按钮无缝轮播 点击数字按钮切换图片 分析:如何实现无缝轮播? 在一个固定大小的相框里有一个ul标签,其长 ...