什么是 Linux inode?用途是什么?
1. 写在前面
Linux inode(index node),自 20 世纪 70 年代末推出第一个 UNIX 文件系统以来就一直存在。90 年代 Linux 引入了相同的概念,并一直沿用至今。很大程度上,整个 Linux 系统正常运行都依赖于 inode。
本文主要介绍 Linux inode 及其相关操作。
2. 什么是 inode?
inode 是一种文件数据结构,用于存储除文件名和数据之外的任何 Linux 文件的信息。
示例:stat 查看 inode:
root@jpzhang-dev:~# stat domain.txt
--------------------------------------------------------------------------------------
File: domain.txt
Size: 30 Blocks: 8 IO Block: 4096 regular file
Device: fc01h/64513d Inode: 6362 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-01-05 01:21:46.196735160 +0800
Modify: 2023-12-29 00:11:28.349067755 +0800
Change: 2023-12-29 00:11:28.349067755 +0800
Birth: -
3. inode 是用来做什么的?
Linux 中,数据以固定大小的块形式存储在磁盘上。如果你保存的文件超过了一个标准块的大小,系统就会查找下一个可用区段来存储文件的其余部分。久而久之,就会变得非常混乱,这时候就需要 inode 了。
inode 虽然不包含文件的任何实际数据,但却存储着文件的元数据,包括可以找到文件数据的所有存储块。
inode 中包含的信息:
- 文件大小;
- 存储文件的设备;
- 与文件相关的用户和组 ID;
- 访问文件所需的权限;
- 创建、读取和写入时间戳;
- 数据位置(但不包括文件路径);
inode 与文件名无关,这意味着可以复制一个文件,重新命名后,它仍然指向与原始文件相同的 inode。
4. inode 是如何工作的?
创建新文件时,会分配一个 inode 编号和一个文件名,inode 编号是文件系统中唯一的编号,文件名和 inode 编号都作为条目存储在目录中。
当运行 ls
命令,如 "ls -li /"时,文件名和 inode 编号是存储在 / 目录中的内容。其余的用户、组、文件权限、大小等信息是使用 inode 编号从 inode 表中获取的。
在 Linux 中使用 df
命令可以列出每个文件系统的 inode 信息:df -hi
5. inode & 软/硬 链接
Linux 中创建符号链接时,inode 会发生什么变化?
示例目录:创建软连接命令 ln -s ../file1 slink
root@jpzhang-dev:~/linux/inode# tree
--------------------------------------------------------------------------------------
.
├── dir
│ └── slink -> ../file1
└── file1
递归列出并显示 inode 信息:
root@jpzhang-dev:~/linux/inode# ls -liR
--------------------------------------------------------------------------------------
.:
total 4
161992 drwxr-xr-x 2 root root 4096 Feb 1 00:08 dir
6108 -rw-r--r-- 1 root root 0 Feb 1 00:04 file1
./dir:
total 0
6247 lrwxrwxrwx 1 root root 8 Feb 1 00:08 slink -> ../file1
可以看到,dir 和 file1 的 inode 编号不同,软链接也一样。创建软链接时,会创建一个新文件,在元数据中,它指向目标文件,每创建一个软链接,就使用一个 inode。
接下来,看下硬链接。
使用 ln 命令在 dir1 中创建硬链接:ln ../file1 hlink1
root@jpzhang-dev:~/linux/inode# tree
--------------------------------------------------------------------------------------
.
├── dir
│ ├── hlink
│ └── slink -> ../file1
└── file1
显示 inode:
root@jpzhang-dev:~/linux/inode# ls -liR
--------------------------------------------------------------------------------------
.:
total 4
161992 drwxr-xr-x 2 root root 4096 Feb 1 00:14 dir
6108 -rw-r--r-- 2 root root 0 Feb 1 00:04 file1
./dir:
total 0
6108 -rw-r--r-- 2 root root 0 Feb 1 00:04 hlink
6247 lrwxrwxrwx 1 root root 8 Feb 1 00:08 slink -> ../file1
可以看到,"file1″ 和 "hlink"的 inode 编号相同。之所以相同是因为:硬链接不会创建新文件,它只是为相同的数据提供了一个新名称。
在旧版本的 Linux 中,可以对目录进行硬链接。甚至可以让某个目录成为自己的父目录。这是因为实现了 inode。现在,为了防止用户创建出非常混乱的目录结构,这点已被限制。
inode 工作方式决定了无法在不同文件系统之间创建硬链接。如果允许这样做,就有可能出现节点编号冲突的情况。而软链接则可以在不同文件系统之间创建。
由于硬链接的 inode 号与原始文件的 inode 号相同,因此可以删除原始文件,但数据仍可通过硬链接使用(如上示例,删除原始文件 file1 情况下,hlink 依旧可以访问)。在这种情况下,你所做的就是删除指向该 inode 编号的其中一个名称。链接到该 inode 编号的数据仍可使用,直到与之相关的所有名称都被删除。
inode 也是 Linux 系统无需重启即可更新的一个重要原因。这是因为一个进程可以使用一个库文件,而另一个进程可以用新版本替换该文件。因此,要为新文件创建一个新的 inode。已经运行的进程将继续使用旧文件,而对它的每次新调用都将使用新版本。
6. 元数据超过 inode 大小
与固定大小的数据块一样,inode 也是统一的。你有可能拥有一个超过你的 inode 大小的文件。在这种情况下,你的原始 inode 必须指向另一个 inode,才能完全包含文件的元数据,这就是所谓的间接指针。
此外,磁盘上的 inode 数量是静态的。这意味着,如果你有足够多的文件,你可能会在磁盘空间用完之前用完 inode。如果你的 inode 用完了,即使给定分区上还有剩余空间,也无法创建新文件。
7. Linux 常用 inode 相关命令
7.1 显示文件系统 inode 信息
使用 df -i
命令查看有关 inode 使用情况,包括存储 inode 的文件系统、总 inode 数量、使用中的数量(数量和百分比)以及剩余数量。
root@jpzhang-dev:~# df -i
--------------------------------------------------------------------------------------
Filesystem Inodes IUsed IFree IUse% Mounted on
udev 2043274 438 2042836 1% /dev
tmpfs 2047671 1008 2046663 1% /run
/dev/vda1 12902400 1437018 11465382 12% /
tmpfs 2047671 1 2047670 1% /dev/shm
tmpfs 2047671 3 2047668 1% /run/lock
tmpfs 2047671 18 2047653 1% /sys/fs/cgroup
/dev/loop0 815 815 0 100% /snap/lxd/24061
/dev/loop1 12041 12041 0 100% /snap/core20/2105
/dev/loop3 658 658 0 100% /snap/snapd/20671
/dev/loop2 658 658 0 100% /snap/snapd/20290
/dev/loop4 11991 11991 0 100% /snap/core20/2015
/dev/vda15 0 0 0 - /boot/efi
或者:root@jpzhang-dev:~# df -i /dev/vda1
7.2 显示指定文件 inode 信息
通过 stat
命令显示指定文件或目录的 inode 信息:
root@jpzhang-dev:~# stat domain.txt
--------------------------------------------------------------------------------------
File: domain.txt
Size: 30 Blocks: 8 IO Block: 4096 regular file
Device: fc01h/64513d Inode: 6362 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-01-05 01:21:46.196735160 +0800
Modify: 2023-12-29 00:11:28.349067755 +0800
Change: 2023-12-29 00:11:28.349067755 +0800
Birth: -
- Size:文件的字节数
- type:文件类型,普通文件,目录,管道等等
- Inode:inode number
- Links:链接数,链接到该 inode 的硬链接数
- Access:读、写、执行权限
- Uid:文件所有者 User ID
- Gid:所有者组 Group ID
- Access:时间戳,最近一次访问的时间
- Modify:时间戳,最近一次修改文件内容的时间
- Change:时间戳,最近一次更改文件的时间(如执行 chmod、chown 等命令)
只列出文件 inode number:
root@jpzhang-dev:~# stat --format=%i domain.txt
--------------------------------------------------------------------------------------
6362
7.3 显示文件 inode number
ls
命令用于列出目录的内容,配合 -i
参数可用于显示每个文件的 inode number:
root@jpzhang-dev:~# ls -i
--------------------------------------------------------------------------------------
2710 README.md 1976 ens3.pcap 96783 linux
使用 -i num
查找与特定 inode 相关的文件
root@jpzhang-dev:~/linux/test# find ./ -inum 2547
--------------------------------------------------------------------------------------
./test.txt
7.4 查看每个inode节点的大小
root@jpzhang-dev:~/linux/test# dumpe2fs -h /dev/vda1 | grep -i "inode size"
--------------------------------------------------------------------------------------
dumpe2fs 1.45.5 (07-Jan-2020)
Inode size: 256