EXT4文件系统学习(9)VFS之磁盘结构inode和direntry

内核版本:linux-4.1.27

inode

索引节点,记录文件的文件属性(mode,time),数据块个数(i_blocks_lo)和位置(i_block[])。

/*
 * Structure of an inode on the disk
 */
struct ext4_inode {
	__le16	i_mode;		/* File mode */
	__le16	i_uid;		/* Low 16 bits of Owner Uid */
	__le32	i_size_lo;	/* Size in bytes */
	__le32	i_atime;	/* Access time */
	__le32	i_ctime;	/* Inode Change time */
	__le32	i_mtime;	/* Modification time */
	__le32	i_dtime;	/* Deletion Time */
	__le16	i_gid;		/* Low 16 bits of Group Id */
	__le16	i_links_count;	/* Links count */
	__le32	i_blocks_lo;	/* Blocks count */
	__le32	i_flags;	/* File flags */
	union {
		struct {
			__le32  l_i_version;
		} linux1;
		struct {
			__u32  h_i_translator;
		} hurd1;
		struct {
			__u32  m_i_reserved1;
		} masix1;
	} osd1;				/* OS dependent 1 */
	__le32	i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
	__le32	i_generation;	/* File version (for NFS) */
	__le32	i_file_acl_lo;	/* File ACL */
	__le32	i_size_high;
	__le32	i_obso_faddr;	/* Obsoleted fragment address */
	union {
		struct {
			__le16	l_i_blocks_high; /* were l_i_reserved1 */
			__le16	l_i_file_acl_high;
			__le16	l_i_uid_high;	/* these 2 fields */
			__le16	l_i_gid_high;	/* were reserved2[0] */
			__le16	l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
			__le16	l_i_reserved;
		} linux2;
		struct {
			__le16	h_i_reserved1;	/* Obsoleted fragment number/size which are removed in ext4 */
			__u16	h_i_mode_high;
			__u16	h_i_uid_high;
			__u16	h_i_gid_high;
			__u32	h_i_author;
		} hurd2;
		struct {
			__le16	h_i_reserved1;	/* Obsoleted fragment number/size which are removed in ext4 */
			__le16	m_i_file_acl_high;
			__u32	m_i_reserved2[2];
		} masix2;
	} osd2;				/* OS dependent 2 */
	__le16	i_extra_isize;
	__le16	i_checksum_hi;	/* crc32c(uuid+inum+inode) BE */
	__le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */
	__le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */
	__le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */
	__le32  i_crtime;       /* File Creation time */
	__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
	__le32  i_version_hi;	/* high 32 bits for 64-bit version */
};

i_flags,文件的标志,其中几个含义如下:

/*
 * Inode flags
 */
#define	EXT4_SECRM_FL			0x00000001 /* Secure deletion */安全删除,删除后会填充随机数
#define	EXT4_UNRM_FL			0x00000002 /* Undelete */可恢复删除,删除文件后数据会保留一段时间内可恢复
#define	EXT4_COMPR_FL			0x00000004 /* Compress file */
#define EXT4_SYNC_FL			0x00000008 /* Synchronous updates */同步写,在写内存过程中同步写入磁盘

i_blocks_lo,表示文件占用的数据块个数,数组i_block保存数据块地址,数组长度12+3=15,代码来源如下:

/*
 * Constants relative to the data blocks
 */
#define	EXT4_NDIR_BLOCKS		12
#define	EXT4_IND_BLOCK			EXT4_NDIR_BLOCKS
#define	EXT4_DIND_BLOCK			(EXT4_IND_BLOCK + 1)
#define	EXT4_TIND_BLOCK			(EXT4_DIND_BLOCK + 1)
#define	EXT4_N_BLOCKS			(EXT4_TIND_BLOCK + 1)

数组长度15只能存储4K block容量为60KB大小的文件,明显不合理,为此前12项直接存储块地址,后3项依次为1级指针、2级指针、3级指针,如下图所示:

通过3级指针存储块地址转换,最大可存储文件大小为4TB。

每个文件都有一个对应inode结构,通过i_block数组能访问到文件的所以数据,但是inode结构体中没有存储文件名,这是为何?

direntry

实际上文件名保存在目录中,目录也是一个文件,也占用一个inode结构,它的数据块存储的是该目录下所以文件的文件名,以及各个文件对应的inode号。

/*
 * Structure of a directory entry
 */
#define EXT4_NAME_LEN 255

struct ext4_dir_entry_2 {
	__le32	inode;			/* Inode number */
	__le16	rec_len;		/* Directory entry length */
	__u8	name_len;		/* Name length */
	__u8	file_type;
	char	name[EXT4_NAME_LEN];	/* File name */
};

inode,存储对应文件的inode号。 

name,存储文件名,最大长度255个字节字符。

file_type,存储文件类型,文件类型如下:

/*
 * Ext4 directory file types.  Only the low 3 bits are used.  The
 * other bits are reserved for now.
 */
#define EXT4_FT_UNKNOWN		0
#define EXT4_FT_REG_FILE	1
#define EXT4_FT_DIR		2
#define EXT4_FT_CHRDEV		3
#define EXT4_FT_BLKDEV		4
#define EXT4_FT_FIFO		5
#define EXT4_FT_SOCK		6
#define EXT4_FT_SYMLINK		7

#define EXT4_FT_MAX		8

在ext4文件系统中,根目录的inode号固定为2,下面列出特殊的inod号:

/*
 * Special inodes numbers
 */
#define	EXT4_BAD_INO		 1	/* Bad blocks inode */
#define EXT4_ROOT_INO		 2	/* Root inode */
#define EXT4_USR_QUOTA_INO	 3	/* User quota inode */
#define EXT4_GRP_QUOTA_INO	 4	/* Group quota inode */
#define EXT4_BOOT_LOADER_INO	 5	/* Boot loader inode */
#define EXT4_UNDEL_DIR_INO	 6	/* Undelete directory inode */
#define EXT4_RESIZE_INO		 7	/* Reserved group descriptors inode */
#define EXT4_JOURNAL_INO	 8	/* Journal inode */

ext4目录项在磁盘上的结构如下图所示:

打印出实际的磁盘目录项结构信息如下图:

每个目录使用direntry保存目录下的文件信息,direntry在磁盘中也是占用一个inode数据结构,inode数据结构中的数据块存储的是该目录下所以文件的文件名,以及各个文件对应的inode号,每个文件的direntry数据信息挨着排列在一个inode中,如上图所示。

定位文件路径位置也是先从direntry开始查找,direntry中保存了文件名信息,如果是多级目录,那么目录文件的inode号又指向下一级目录的direntry的inode。

为什么每级目录下要有.和..两个目录?如果没有这2个目录,那么每次查找文件路径必须从根目录开始查找,这样过于繁琐且效率不高。有了这2个目录,就可以从当前目录出发开始向下一级或者向上一级开始查找,这样效率会高很多。

链接文件

Linux中,为一个文件建立别名称为链接文件。分为软连接和硬链接。

  • 硬链接

硬链接文件与原文件的inode号是一致的且相同,没有占用额外的inode空间,硬链接文件通过ls -li查看inode号是一致的,且看不出软连接那样的->符号。

硬链接不能跨越文件系统,因为内核打开硬链接文件只会在当前文件系统中查找对应的inode号,所以即便是2个相同的文件系统之间也不能建立硬链接文件。

  • 软连接

又称为符号链接,添加参数-s实现,与原文件的inode号不一致,会占用额外的inode空间,如果文件大于block 4kb * 15 = 60KB的话还会占用额外的数据块了。

软连接可以跨越文件系统。

 

猜你喜欢

转载自blog.csdn.net/TSZ0000/article/details/87188128
今日推荐