磁盤→盤片→磁道→扇區(每一個 512 字節)node
ext* 定義文件系統的格式數據結構
咱們能夠分散成一個個小塊進行存放函數
至於 inode 裏面有哪些信息,其實咱們在內核中就有定義。你能夠看下面這個數據結構。佈局
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 */ ...... __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; ...... };
一、什麼是inode?性能
二、基本信息ui
三、時間相關信息spa
四、i_blocks_lo3d
五、i_blockorm
具體如何保存的呢?EXT4_N_BLOCKS 有以下的定義,blog
#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
一、如何保存?
二、文件比較大12塊放不下?
三、文件再大些
四、文件更大一些
五、存在問題
ext4 引入 Extents 概念, 能夠用於存放連續的數據塊
優勢:對於大文件的讀寫性能提升了,文件碎片也減小了
ext4_extent_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 */ };
/* * This is the extent on-disk structure. * It's used at the bottom of the tree. */ 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; };
一、位圖
二、塊組
上海虹橋火車站的廁位智能引導系統,不知道你有沒有見過?這個系統很厲害,咱們要想知道哪一個位置有沒有被佔用,不用挨個拉門,從這樣一個電子版上就能看到了
do_sys_open
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) { if (force_o_largefile()) flags |= O_LARGEFILE; return do_sys_open(AT_FDCWD, filename, flags, mode); }
inode 操做的調用鏈
一、要打開一個文件,先要根據路徑找到文件夾、若是發現文件夾下面沒有這個文件,同時又設置了 O_CREAT
二、就說明咱們要在這個文件夾下面建立一個文件,那咱們就須要一個新inode
static int lookup_open(struct nameidata *nd, struct path *path, struct file *file, const struct open_flags *op, bool got_write, int *opened) { ...... if (!dentry->d_inode && (open_flag & O_CREAT)) { ...... error = dir_inode->i_op->create(dir_inode, dentry, mode, open_flag & O_EXCL); ...... } ...... }
想要建立新的 inode,咱們就要調用 dir_inode,
也就是文件夾的 inode 的 create 函數。它的具體定義是這樣
const struct inode_operations ext4_dir_inode_operations = { .create = ext4_create, .lookup = ext4_lookup, .link = ext4_link, .unlink = ext4_unlink, .symlink = ext4_symlink, .mkdir = ext4_mkdir, .rmdir = ext4_rmdir, .mknod = ext4_mknod, .tmpfile = ext4_tmpfile, .rename = ext4_rename2, .setattr = ext4_setattr, .getattr = ext4_getattr, .listxattr = ext4_listxattr, .get_acl = ext4_get_acl, .set_acl = ext4_set_acl, .fiemap = ext4_fiemap, };
接下來的調用鏈是這樣
struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, const struct qstr *qstr, __u32 goal, uid_t *owner, __u32 i_flags, int handle_type, unsigned int line_no, int nblocks) { ...... inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); ...... ino = ext4_find_next_zero_bit((unsigned long *) inode_bitmap_bh->b_data, EXT4_INODES_PER_GROUP(sb), ino); ...... }
一個位圖只能表示 2^15 個數據塊, 即 128MB
一、塊組
超級塊 ext4_super_block
一個 inode 位圖 + 一個 block 位圖, 稱爲塊組, 用數據結構 ext4_group_desc 表示, 裏面包含 inode 位圖, block 位圖和 inode 列表
這些塊組描述符構成列表, 另外用超級塊 ext4_super_block 描述整個文件系統; 第一個塊組前 1k 用於啓動引導
文件系統的組成
文件系統由引導塊 + N 個塊組組成; 每一個塊組由: 超級塊 + 塊組描述符表 + 塊位圖 + inode 位圖 + inode 列表 + 數據塊構成
超級塊和塊組描述符表都是全局信息; 默認超級塊和塊組描述符表再滅個租客都有備份; 若開啓 sparse_super, 則只在固定塊組中備份
採用 Meta Block Groups 特性, 避免塊組表浪費空間, 或限制文件系統的大小
- 將塊組分紅多個組(元塊組) 塊組描述符表只保存當前元塊組中塊組的信息, 並在元塊組內備份
struct ext4_super_block { ...... __le32 s_blocks_count_lo; /* Blocks count */ __le32 s_r_blocks_count_lo; /* Reserved blocks count */ __le32 s_free_blocks_count_lo; /* Free blocks count */ ...... __le32 s_blocks_count_hi; /* Blocks count */ __le32 s_r_blocks_count_hi; /* Reserved blocks count */ __le32 s_free_blocks_count_hi; /* Free blocks count */ ...... }
目錄也是文件, 也有 inode, inode 指向一個塊, 塊中保存各個文件信息, ext4_dir_entry 包括文件名和 inode, 默認按列表存
struct ext4_dir_entry { __le32 inode; /* Inode number */ __le16 rec_len; /* Directory entry length */ __le16 name_len; /* Name length */ char name[EXT4_NAME_LEN]; /* File name */ }; 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 */ };
第一項 "." 當前目錄; 第二項 ".." 上一級目錄
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; };
須要改變目錄塊格式, 加入索引樹: 用索引項 dx_entry 保存文件名哈希和塊的映射, 若該塊不是索引, 則裏面保存 ext4_dir_enry 列表, 逐項查找
一、連接即文件的別名: ln -s 建立軟連接; ln 建立硬連接
二、硬連接與原始文件共用一個 inode, 但不能跨文件系統
三、軟連接是一個文件, 有本身的 inode, 該文件內容指向另外一個文件, 可跨文件系統
這一節,咱們描述了複雜的應哦按上的文件系統,可是對於我們平時的應用來說,用的最多的是兩個概念,一個是inode、一個是數據塊
爲了表示圖中上半部分的那個簡單的樹形結構,在文件系統上的佈局就像圖的下半部分同樣,不管是文件夾仍是文件,都有一個inode,inode裏面的會指向數據塊,對於文件夾的數據塊,裏面是一個表,是下一層的文件和inode的對應關係,文件的數據塊裏面存放的是真正的數據