Linux--存储系统探秘:从块设备到inode
想象一下,当你轻轻敲下ls -l
命令时,背后正上演着一场精彩绝伦的"数据寻宝记"💎;当你创建或删除文件时,系统底层正在进行着精密的"数字积木游戏"🎮。这些看似简单的操作背后,隐藏着Linux文件系统精心设计的存储架构。
在这篇博客中,你将了解到:
-
块(Block):数据存储的基本单位,就像乐高积木一样构建起整个文件世界🧱
-
分区(Partition):如何将物理磁盘划分为逻辑独立的存储王国🍰
-
inode:文件的"基因密码",记录着所有关键属性信息🧬
-
目录与文件名:Linux如何巧妙管理(inode, 文件名)的映射关系🗺️
准备好你的"探险装备"🔦,让我们开始这段奇妙的Linux存储系统探索之旅吧!每一段知识都像一颗等待被发现的宝石💎,而你就是那位幸运的寻宝者!
1.“块”的概念
🔍 块(Block)是什么?
想象一下硬盘就像一座巨大的"数据乐高城"🏙️,而"块"就是构建这座城市的最小积木单位!操作系统可不会一块一块地搬积木(那太慢啦🐢),而是一次性搬一整组积木🚚,这就是"块"的精妙之处!
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样
效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个”块”(block)。
硬盘的每个分区是被划分为⼀个个的”块”。⼀个”块”的⼤⼩是由格式化的时候确定的,并且不可
以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个 ”块”。”块”是⽂件存取的最⼩单位。
[ljh@lijunhua-allcloud stdio]$ stat main.c
File: 'main.c'
Size: 488 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/647694 Inode: 1052007 Links: 1
Access: (0664/-rw-rw-r--) Uid: (1000/ whb) Gid: (1000/ whb)
Access: 2024-10-25 22:15:52.909616443 +0800
Modify: 2024-10-17 19:06:11.139423737 +0800
Change: 2024-10-17 19:06:11.139423737 +0800
Birth: -
看这个有趣的stat命令输出🔍:
-
文件大小只有488字节📏,但却占用了8个Blocks!
-
每个Block大小是4096字节(4KB)🧩
-
就像把一个小玩具放进大箱子📦,虽然浪费了点空间,但搬运效率大大提高🚀
🧮 块的寻址魔法 注意:
磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇区
每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。
块号 = LBA/8
LBA=块号*8 + n. (n是块内第⼏个扇区)
🌟 为什么要有块?
效率之王👑:一次性读取多个扇区,就像用购物车🛒而不是手提篮买东西
空间管理大师🧙♂️:即使文件很小,也至少占用一个块,就像最小包装单位
系统基石🏗️:所有文件操作最终都要落实到块的操作
💡 小贴士:块大小在格式化时就确定了,就像乐高积木的规格,一旦确定就不能轻易改变哦!
2.“分区”的概念
🎂 什么是磁盘分区?
想象你的硬盘是一个超大的生日蛋糕🎂,分区就像把这个蛋糕切成几块:
Windows世界:C盘、D盘、E盘...就像把蛋糕切成几块分给不同朋友🍰
Linux世界:虽然也是切蛋糕,但我们用更优雅的"文件式"管理方式📁
🔧 分区的本质
分区实际上是对硬盘进行"高级格式化"✨:
物理层面:在蛋糕上划出分界线
逻辑层面:为每块蛋糕准备不同的盘子(文件系统)
# 查看磁盘分区情况的魔法命令🔮
sudo fdisk -l
Disk /dev/sda: 500GB
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1026047 1024000 500M 83 Linux
/dev/sda2 1026048 976771071 975745024 465.3G 8e Linux LVM
🧮 柱面:分区的"最小计量单位"
硬盘就像由无数个"柱面甜甜圈"🍩堆叠而成的圆柱体:
柱面编号:每个甜甜圈都有唯一编号
分区规划:只需要记录起始和结束的甜甜圈编号
💡 专业小知识:
知道起始柱面号 + 每个柱面的扇区数 = 就能计算出LBA范围!
这就像知道蛋糕切块的起止位置就能算出这块有多大📏
我们可以利⽤参考柱⾯号码的⽅式来进⾏分区,其本质就是设置每个区的起始柱⾯和结束柱⾯号码。 此时我们可以将硬盘上的柱⾯(分区)进⾏平铺,将其想象成⼀个⼤的平⾯,如下图所⽰:
3.“inode”的概念
📌 文件的双重身份:数据+属性
在Linux世界里,每个文件都像一位公民👤,拥有:
身体(文件数据)💾
身份证(文件属性)🆔
之前我们说过 ⽂件=数据+属性 ,我们使⽤ ls -l 的时候看到的除了看到⽂件名,还能看到⽂件元
数据(属性)。
# ls -l
总⽤量 12
-rwxr-xr-x. 1 root root 7438 "9⽉ 13 14:56" a.out
-rw-r--r--. 1 root root 654 "9⽉ 13 14:56" test.c
每⾏包含7列:
• 模式
• 硬链接数
• ⽂件所有者
• 组
• ⼤⼩
• 最后修改时间
• ⽂件名
ls -l读取存储在磁盘上的⽂件信息,然后显⽰出来
🔍 inode:文件的"基因库"
这个信息除了通过这种⽅式来读取,还有⼀个stat命令能够看到更多信息
[root@localhost linux]# stat test.c
File: "test.c"
Size: 654 Blocks: 8 IO Block: 4096 普通⽂件
Device: 802h/2050d Inode: 263715 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-09-13 14:56:57.059012947 +0800
Modify: 2017-09-13 14:56:40.067012944 +0800
Change: 2017-09-13 14:56:40.069012948 +0800
到这我们要思考⼀个问题,⽂件数据都储存在”块”中,那么很显然,我们还必须找到⼀个地⽅储存
⽂件的元信息(属性信息),⽐如⽂件的创建者、⽂件的创建⽇期、⽂件的⼤⼩等等。这种储存⽂件元信息的区域就叫做inode,中⽂译名为”索引节点”。
[ljh@lijunhua-alicloud stdio]$ ls -li
total 16
1052669 -rw-rw-r-- 1 ljh ljh 225 Oct 17 19:09
1052007 -rw-rw-r-- 1 ljh ljh 488 Oct 17 19:06
1052661 -rw-rw-r-- 1 ljh ljh 1496 Oct 17 19:11
1052662 -rw-rw-r-- 1 ljh ljh 447 Oct 17 18:53
每⼀个⽂件都有对应的inode,⾥⾯包含了与该⽂件有关的⼀些信息。为了能解释清楚inode,我们需要是深⼊了解⼀下⽂件系统。
🧬 inode数据结构解剖
inode就像文件的"DNA序列"🧬,在ext2文件系统中是这样定义的:
struct ext2_inode {__le16 i_mode; /* File mode */__le16 i_uid; /* Low 16 bits of Owner Uid */__le32 i_size; /* Size in bytes */__le32 i_atime; /* Access time */__le32 i_ctime; /* Creation 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; /* Blocks count */__le32 i_flags; /* File flags */union {struct {__le32 l_i_reserved1;} linux1;struct {__le32 h_i_translator;} hurd1;struct {__le32 m_i_reserved1;} masix1;} osd1; /* OS dependent 1 */__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */__le32 i_generation; /* File version (for NFS) */__le32 i_file_acl; /* File ACL */__le32 i_dir_acl; /* Directory ACL */__le32 i_faddr; /* Fragment address */union {struct {__u8 l_i_frag; /* Fragment number */__u8 l_i_fsize; /* Fragment size */__u16 i_pad1;__le16 l_i_uid_high; /* these 2 fields */__le16 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 */__le16 h_i_mode_high;__le16 h_i_uid_high;__le16 h_i_gid_high;__le32 h_i_author;} hurd2;struct {__u8 m_i_frag; /* Fragment number */__u8 m_i_fsize; /* Fragment size */__u16 m_pad1;__u32 m_i_reserved2[2];} masix2;} osd2; /* OS dependent 2 */
};/** Constants relative to the data blocks*/
#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)备注: EXT2_N_BLOCKS = 15
💡 关于inode的冷知识
唯一标识:每个inode号在分区内是唯一的,就像身份证号👤,Linux下,保存⽂件属性的集合叫做inode,⼀个⽂件,⼀个inode,inode内有⼀个唯⼀的标识符,叫做inode号。
固定大小:通常128或256字节,无论文件内容多大,任何⽂件的内容⼤⼩可以不同,但是属性⼤⼩⼀定是相同的。
内容分离:文件名不在inode中!它存储在目录文件里📁
到⽬前为⽌,相信⼤家还有两个问题:
1. 我们已经知道硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,读取的基本单位
是”块”。“块”⼜是硬盘的每个分区下的结构,难道“块”是随意的在分区上排布的吗?那要怎
么找到“块”呢?
2. 还有就是上⾯提到的存储⽂件属性的inode,⼜是如何放置的呢?
⽂件系统就是为了组织管理这些的!!
知道的小伙伴可以在评论区讨论一下,不知道的小伙伴也没关系,下一篇博客立马向你解释!!!