索引节点和目录项
文件系统,自身是对存储设备上的文件,进行组织治理的机制。组织形式不同,就会造成不同的文件系统。你要记住最重要的一点,在 Linux 中所有皆文件。不仅一般的文件和目录,就连块设施、套接字、管道等,也都要通过对立的文件系统来治理。Linux 文件系统为每个文件都调配两个数据结构,索引节点(index node)和目录项(directory entry)。它们次要用来记录文件的元信息和目录构造
- 索引节点,简称为 inode,用来记录文件的元数据,比方 inode 编号、文件大小、拜访权限、批改日期、数据的地位等。索引节点和文件一一对应,它跟文件内容一样,都会被长久化存储到磁盘中。所以记住,索引节点同样占用磁盘空间。
- 目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其余目录项的关联关系。多个关联的目录项,就形成了文件系统的目录构造。不过,不同于索引节点,目录项是由内核保护的一个内存数据结构,所以通常也被叫做目录项缓存。
换句话说,索引节点是每个文件的惟一标记,而目录项保护的正是文件系统的树状构造。目录项和索引节点的关系是多对一,你能够简略了解为,一个文件能够有多个别名。举个例子,通过硬链接为文件创建的别名,就会对应不同的目录项,不过这些目录项实质上还是链接同一个文件,所以,它们的索引节点雷同。索引节点和目录项纪录了文件的元数据,以及文件间的目录关系,那么具体来说,文件数据到底是怎么存储的呢?是不是间接写到磁盘中就好了呢?实际上,磁盘读写的最小单位是扇区,然而扇区只有 512B 大小,如果每次都读写这么小的单位,效率肯定很低。所以,文件系统又把间断的扇区组成了逻辑块,而后每次都以逻辑块为最小单元,来治理数据。常见的逻辑块大小为 4KB,也就是由间断的 8 个扇区组成。
- 目录项自身就是一个内存缓存,而索引节点则是存储在磁盘中的数据。在后面的 Buffer 和 Cache 原理中,我已经提到过,为了协调慢速磁盘与疾速 CPU 的性能差别,文件内容会缓存到页缓存 Cache 中
- 磁盘在执行文件系统格式化时,会被分成三个存储区域,超级块、索引节点区和数据块区。其中,超级块,存储整个文件系统的状态。索引节点区,用来存储索引节点。数据块区,则用来存储文件数据。
内核应用 Slab 机制,治理目录项和索引节点的缓存。/proc/meminfo 只给出了 Slab 的整体大小,具体到每一种 Slab 缓存,还要查看 /proc/slabinfo 这个文件查看所有目录项和各种文件系统索引节点的缓存状况
[root@VM-4-5-centos lighthouse]# 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>
isofs_inode_cache 46 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0
ext4_inode_cache 4644 4644 1176 27 8 : tunables 0 0 0 : slabdata 172 172 0
jbd2_inode 128 128 64 64 1 : tunables 0 0 0 : slabdata 2 2 0
mqueue_inode_cache 16 16 1024 16 4 : tunables 0 0 0 : slabdata 1 1 0
hugetlbfs_inode_cache 24 24 680 12 2 : tunables 0 0 0 : slabdata 2 2 0
inotify_inode_mark 102 102 80 51 1 : tunables 0 0 0 : slabdata 2 2 0
sock_inode_cache 253 253 704 23 4 : tunables 0 0 0 : slabdata 11 11 0
proc_inode_cache 3168 3322 728 22 4 : tunables 0 0 0 : slabdata 151 151 0
shmem_inode_cache 882 882 768 21 4 : tunables 0 0 0 : slabdata 42 42 0
inode_cache 14688 14748 656 12 2 : tunables 0 0 0 : slabdata 1229 1229 0
dentry 27531 27531 192 21 1 : tunables 0 0 0 : slabdata 1311 1311 0
selinux_inode_security 16626 16626 40 102 1 : tunables 0 0 0 : slabdata 163 163 0
dentry 行示意目录项缓存,inode_cache 行,示意 VFS 索引节点缓存,其余的则是各种文件系统的索引节点缓存。在理论性能剖析中,咱们更常应用 slabtop,来找到占用内存最多的缓存类型
[root@VM-4-5-centos lighthouse]#slabtop
Active / Total Objects (% used) : 223087 / 225417 (99.0%)
Active / Total Slabs (% used) : 7310 / 7310 (100.0%)
Active / Total Caches (% used) : 138 / 207 (66.7%)
Active / Total Size (% used) : 50536.41K / 51570.46K (98.0%)
Minimum / Average / Maximum Object : 0.01K / 0.23K / 8.00K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
29295 28879 98% 0.19K 1395 21 5580K dentry
27150 27150 100% 0.13K 905 30 3620K kernfs_node_cache
26112 25802 98% 0.03K 204 128 816K kmalloc-32
23010 23010 100% 0.10K 590 39 2360K buffer_head
16626 16626 100% 0.04K 163 102 652K selinux_inode_security
14856 14764 99% 0.64K 1238 12 9904K inode_cache
9894 9894 100% 0.04K 97 102 388K ext4_extent_status
6698 6698 100% 0.23K 394 17 1576K vm_area_struct
5508 5508 100% 1.15K 204 27 6528K ext4_inode_cache
5120 5120 100% 0.02K 20 256 80K kmalloc-16
4672 4630 99% 0.06K 73 64 292K kmalloc-64
4564 4564 100% 0.57K 326 14 2608K radix_tree_node
4480 4480 100% 0.06K 70 64 280K anon_vma_chain
4096 4096 100% 0.01K 8 512 32K kmalloc-8
3570 3570 100% 0.05K 42 85 168K ftrace_event_field
3168 2967 93% 0.71K 144 22 2304K proc_inode_cache
3003 2961 98% 0.19K 143 21 572K kmalloc-192
2898 2422 83% 0.09K 63 46 252K anon_vma
2368 1944 82% 0.25K 148 16 592K filp
2080 2075 99% 0.50K 130 16 1040K kmalloc-512
2016 2016 100% 0.07K 36 56 144K Acpi-Operand
1760 1760 100% 0.12K 55 32 220K kmalloc-128
1596 1596 100% 0.09K 38 42 152K kmalloc-96
1472 1472 100% 0.09K 32 46 128K trace_event_file
虚构文件系统
目录项、索引节点、逻辑块以及超级块,形成了 Linux 文件系统的四大基本要素。不过,为了反对各种不同的文件系统,Linux 内核在用户过程和文件系统的两头,又引入了一个形象层,也就是虚构文件系统 VFS(Virtual File System)。VFS 定义了一组所有文件系统都反对的数据结构和标准接口。这样,用户过程和内核中的其余子系统,只须要跟 VFS 提供的对立接口进行交互就能够了,而不须要再关怀底层各种文件系统的实现细节。