Linux 文件系統(tǒng)原理
索引節(jié)點(diǎn)和目錄項(xiàng)
在 Linux 中,一切皆文件,為了方便管理,Linux 文件系統(tǒng)為每個(gè)文件都分配兩個(gè)數(shù)據(jù)結(jié)構(gòu),索引節(jié)點(diǎn)(index node)和目錄項(xiàng)(directory entry)。它們主要用來(lái)記錄文件的元信息和目錄結(jié)構(gòu)。
- 索引節(jié)點(diǎn),簡(jiǎn)稱(chēng)為 inode,用來(lái)記錄文件的元數(shù)據(jù),比如 inode 編號(hào)、文件大小、訪問(wèn)權(quán)限、修改日期、數(shù)據(jù)的位置等。索引節(jié)點(diǎn)和文件一一對(duì)應(yīng),它跟文件內(nèi)容一樣,都會(huì)被持久化存儲(chǔ)到磁盤(pán)中。所以記住,索引節(jié)點(diǎn)同樣占用磁盤(pán)空間。
-
目錄項(xiàng),簡(jiǎn)稱(chēng)為 dentry,用來(lái)記錄文件的名字、索引節(jié)點(diǎn)指針以及與其他目錄項(xiàng)的關(guān)聯(lián)關(guān)系。多個(gè)關(guān)聯(lián)的目錄項(xiàng),就構(gòu)成了文件系統(tǒng)的目錄結(jié)構(gòu)。不過(guò),不同于索引節(jié)點(diǎn),目錄項(xiàng)是由內(nèi)核維護(hù)的一個(gè)內(nèi)存數(shù)據(jù)結(jié)構(gòu),所以通常也被叫做目錄項(xiàng)緩存。
如下圖所示:
image.png
需要注意的是:
- 目錄項(xiàng)本身就是一個(gè)內(nèi)存緩存,而索引節(jié)點(diǎn)則是存儲(chǔ)在磁盤(pán)中的數(shù)據(jù),所以,索引節(jié)點(diǎn)也會(huì)緩存到內(nèi)存中,從而加速文件的訪問(wèn)。
- 磁盤(pán)在執(zhí)行文件系統(tǒng)格式化時(shí),會(huì)被分成三個(gè)存儲(chǔ)區(qū)域,超級(jí)塊、索引節(jié)點(diǎn)區(qū)和數(shù)據(jù)塊區(qū)。超級(jí)塊,存儲(chǔ)整個(gè)文件系統(tǒng)的狀態(tài)。索引節(jié)點(diǎn)區(qū),用來(lái)存儲(chǔ)索引節(jié)點(diǎn)。數(shù)據(jù)塊區(qū),則用來(lái)存儲(chǔ)文件數(shù)據(jù)。
虛擬文件系統(tǒng)
目錄項(xiàng)、索引節(jié)點(diǎn)、邏輯塊以及超級(jí)塊,構(gòu)成了 Linux 文件系統(tǒng)的四大基本要素。不過(guò),為了支持各種不同的文件系統(tǒng),Linux 內(nèi)核在用戶(hù)進(jìn)程和文件系統(tǒng)的中間,又引入了一個(gè)抽象層,也就是虛擬文件系統(tǒng) VFS(Virtual File System)。

文件系統(tǒng)的觀測(cè)指標(biāo)
容量
文件系統(tǒng)的磁盤(pán)空間使用情況
df -Th /dev/vda1
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 99G 77G 19G 81% /
另外,inode 也會(huì)占用磁盤(pán)空間
df -i /dev/vda1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 6553600 1411937 5141663 22% /
緩存
實(shí)際上,內(nèi)核使用 Slab 機(jī)制,管理目錄項(xiàng)和索引節(jié)點(diǎn)的緩存。/proc/meminfo 只給出了 Slab 的整體大小,具體到每一種 Slab 緩存,還要查看 /proc/slabinfo 這個(gè)文件
cat /proc/slabinfo | grep -E '^#|dentry|inode'
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
nfs_inode_cache 7781 16590 1120 29 8 : tunables 0 0 0 : slabdata 590 590 0
ovl_inode 139738 160300 720 45 8 : tunables 0 0 0 : slabdata 3564 3564 0
rpc_inode_cache 920 920 704 46 8 : tunables 0 0 0 : slabdata 20 20 0
xfs_inode 329696 511911 1088 30 8 : tunables 0 0 0 : slabdata 17070 17070 0
fuse_inode 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0
mqueue_inode_cache 1054 1054 960 34 8 : tunables 0 0 0 : slabdata 31 31 0
udf_inode_cache 0 0 816 40 8 : tunables 0 0 0 : slabdata 0 0 0
isofs_inode_cache 987 987 688 47 8 : tunables 0 0 0 : slabdata 21 21 0
fat_inode_cache 0 0 776 42 8 : tunables 0 0 0 : slabdata 0 0 0
jbd2_inode 22819 50816 64 64 1 : tunables 0 0 0 : slabdata 794 794 0
ext2_inode_cache 0 0 864 37 8 : tunables 0 0 0 : slabdata 0 0 0
ext4_inode_cache 135042 265177 1152 28 8 : tunables 0 0 0 : slabdata 9609 9609 0
hugetlbfs_inode_cache 48 48 664 24 4 : tunables 0 0 0 : slabdata 2 2 0
inotify_inode_mark 52071 52275 80 51 1 : tunables 0 0 0 : slabdata 1025 1025 0
sock_inode_cache 74776 75040 832 39 8 : tunables 0 0 0 : slabdata 1925 1925 0
proc_inode_cache 217797 222471 712 46 8 : tunables 0 0 0 : slabdata 4839 4839 0
shmem_inode_cache 29175 31218 752 43 8 : tunables 0 0 0 : slabdata 726 726 0
inode_cache 176590 178181 640 25 4 : tunables 0 0 0 : slabdata 7128 7128 0
dentry 4171929 13868208 224 36 2 : tunables 0 0 0 : slabdata 385231 385231 0
其中,dentry 行表示目錄項(xiàng)緩存,inode_cache 行,表示 VFS 索引節(jié)點(diǎn)緩存,其余的則是各種文件系統(tǒng)的索引節(jié)點(diǎn)緩存。
實(shí)際性能分析中,我們更常使用 slabtop ,來(lái)找到占用內(nèi)存最多的緩存類(lèi)型。
# 按下c按照緩存大小排序,按下a按照活躍對(duì)象數(shù)排序
$ slabtop
Active / Total Objects (% used) : 14703586 / 26109197 (56.3%)
Active / Total Slabs (% used) : 672727 / 672727 (100.0%)
Active / Total Caches (% used) : 187 / 273 (68.5%)
Active / Total Size (% used) : 3634188.87K / 6402995.95K (56.8%)
Minimum / Average / Maximum Object : 0.01K / 0.25K / 10.19K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
13884516 4184714 30% 0.22K 385684 36 3085472K dentry
512121 330274 64% 1.06K 17077 30 546464K xfs_inode
618562 325811 52% 0.57K 22108 28 353728K radix_tree_node
265177 135042 50% 1.12K 9609 28 307488K ext4_inode_cache
282828 270095 95% 1.00K 8855 32 283360K kmalloc-1k
1898550 1883641 99% 0.13K 63285 30 253140K kernfs_node_cache
223391 218976 98% 0.70K 4859 46 155488K proc_inode_cache
180631 179228 99% 0.62K 7226 25 115616K inode_cache
160300 139738 87% 0.70K 3564 45 114048K ovl_inode
844896 577538 68% 0.10K 21664 39 86656K buffer_head
7503 7213 96% 10.19K 2505 3 80160K task_struct
15976 15705 98% 4.00K 1997 8 63904K kmalloc-4k
199375 192826 96% 0.31K 7975 25 63800K filp
262412 260230 99% 0.23K 7718 34 61744K vm_area_struct
Linux磁盤(pán) I/O
I/O性能指標(biāo)
- 使用率,是指磁盤(pán)處理 IO 的時(shí)間百分比,過(guò)高的使用率(比如超過(guò) 80%),通常以為著磁盤(pán) IO 存在著性能瓶頸。
- 飽和度,是指磁盤(pán)處理 IO 的繁忙程度,過(guò)高的磁盤(pán)飽和度意味著磁盤(pán)存在著嚴(yán)重的性能瓶頸,當(dāng)飽和度為 100% 時(shí),則意味著磁盤(pán)無(wú)法接受新的 IO 請(qǐng)求。
- IOPS,是指每秒的IO 請(qǐng)求數(shù)。
- 吞吐量,是指每秒的 IO 請(qǐng)求大小。
- 響應(yīng)時(shí)間,是指 IO 請(qǐng)求從發(fā)出到接受響應(yīng)的間隔時(shí)間。
I/O指標(biāo)觀測(cè)工具
iostat
iostat 是最常用的磁盤(pán) I/O 性能觀測(cè)工具,它提供了每個(gè)磁盤(pán)的使用率、IOPS、吞吐量等各種常見(jiàn)的性能指標(biāo),當(dāng)然,這些指標(biāo)實(shí)際上來(lái)自 /proc/diskstats。
-d -x表示顯示所有磁盤(pán)I/O的指標(biāo)
$ iostat -d -x 1
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
loop0 0.00 0.00 0.03 0.00 0.00 0.00 0.00 0.00 0.06 0.00 0.00 118.64 0.00 0.47 0.00
vda 2.54 25.39 16.88 291.39 0.62 23.70 19.73 48.29 0.76 1.46 0.02 6.65 11.48 0.91 2.53
vdb 0.11 4.21 7.68 101.42 0.00 0.63 0.44 13.08 2.39 3.91 0.01 69.19 24.09 1.02 0.44
指標(biāo)說(shuō)明:
- %util ,就是我們前面提到的磁盤(pán) I/O 使用率;
- r/s+ w/s ,就是 IOPS;\
- rkB/s+wkB/s ,就是吞吐量;
- r_await+w_await ,就是響應(yīng)時(shí)間。
進(jìn)程 IO 觀測(cè)
pidstat工具
pidstat -d 1
Linux 5.4.203-1-tlinux4-0011.1 (VM-167-17-tencentos) 01/27/2024 _x86_64_ (16 CPU)
08:18:40 AM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
08:18:41 AM 0 460 0.00 78.43 0.00 1 jbd2/vda1-8
08:18:41 AM 0 25009 0.00 3.92 0.00 0 containerd
08:18:41 AM 0 25653 0.00 70.59 0.00 0 etcd
08:18:41 AM 999 1236567 0.00 101.96 0.00 0 mysqld
- 用戶(hù) ID(UID)和進(jìn)程 ID(PID) 。
- 每秒讀取的數(shù)據(jù)大?。╧B_rd/s) ,單位是 KB。
- 每秒發(fā)出的寫(xiě)請(qǐng)求數(shù)據(jù)大小(kB_wr/s) ,單位是 KB。
- 每秒取消的寫(xiě)請(qǐng)求數(shù)據(jù)大小(kB_ccwr/s) ,單位是 KB。
- 塊 I/O 延遲(iodelay),包括等待同步塊 I/O 和換入塊 I/O 結(jié)束的時(shí)間,單位是時(shí)鐘周期。
iotop工具
$ iotop
Total DISK READ : 0.00 B/s | Total DISK WRITE : 7.85 K/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
15055 be/3 root 0.00 B/s 7.85 K/s 0.00 % 0.00 % systemd-journald
