详解Linux Inode
一切都是文件,Linux 和其他类 Unix 操作系统通过将所有内容都视为文件(甚至是硬件设备)来保持一致性。 键盘,鼠标,打印机,显示器,硬盘,进程,甚至目录都被视为 Linux 中的文件。 常规文件包含文本(文本文件),音乐,视频(多媒体文件)等数据。除常规数据外,还有一些关于这些文件的其他数据,例如它们的大小,所有权,权限,时间戳等。 有关文件的元数据使用称为 inode(索引节点)的数据结构进行管理。
什么是 inode?#
每个 Linux 文件或目录 (从技术角度讲,它们之间没有本质的区别) 都有一个 inode,而这个 inode 包含了所有文件的元数据 (也就是说,读取文件所需的管理数据都存储在 inode 中)。例如,inode 包含存储文件的所有块的列表,该文件所有者信息、权限以及为该文件设置的所有其他属性。从某种意义上讲,你可以说文件就是 inode,并且文件名被附加到 inode 上以使人们更容易使用它们。
inode 在文件系统创建是确定,并且每个文件系统都有一个 inode 集合。最大的目录大小取决于不同的文件系统。为了获得更好的性能,通常将文件放入不同的子目录中,而不是将所有文件放入同一个目录。
什么是 inode number#
inode 是 inode table 中的一个条目,包含有关目录和常规文件的元数据。inode 是传统 Unix 风格文件系统 (比如 ext3/ext4) 上的数据结构。Linux 扩展文件系统 (如 ext2/ext3) 维护了一个 inode 的数组:inode table。inode table 包含该文件系统中所有文件的列表。inode table 中的各个 inode 项具有唯一的编号 (该文件系统唯一),即 inode number。深入 inode 数据结构,我们发现它存储了如下信息:
- 文件类型: 普通文件,目录,管道等等
- 权限:可读,可写,可执行
- 链接数:链接到该 inode 的硬链接数
- User ID:文件所有者
- Group ID:所有者组 ID
- 文件大小
- 时间信息
- 属性:比如,不可改变位
- 访问控制列表
- 文件数据存储的实际位置
- 其他元数据
注意:inode 中不存储文件名数据
如何查看 inode 信息#
如果你希望查看文件系统的 inode 信息,你可以使用一些 shell 命令来查看文件系统的属性
a. 显示指定文件信息#
你可以使用 stat 命令显示某个文件或目录的 inode 信息,你必须指定文件或目录名
# stat log.txt
File: 'log.txt'
Size: 212 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 591912 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-11-26 11:27:13.683598803 +0800
Modify: 2018-12-06 17:18:49.799424595 +0800
Change: 2018-12-06 17:18:49.799424595 +0800
Birth: -
命令的输出告诉了你该文件的各种时间信息,它的所有权和权限,以及文件存储的位置。存储文件数据的磁盘块信息也展示在 stat 命令的输出中。
你也可以选择只列出文件的 inode number:
# stat --format=%i log.txt
591912
b. 打印文件的 inode number#
ls 命令用于列出文件 / 文件夹的信息。参数 -i
说明需要显示每个文件的 inode number。我们可以结合参数 -l
一起使用以列出详细信息:
# ls -li
total 16
592404 drwxr-xr-x 6 root root 4096 Nov 2 15:01 config
591900 -rw-r--r-- 1 root root 453 Nov 25 22:25 docker-compose-single.yml
592414 -rw-r--r-- 1 root root 2714 Nov 2 15:01 docker-compose.yml
592415 drwxr-xr-x 2 root root 4096 Nov 2 15:01 mariadb
输出的第一列显示了文件的 inode number。
c. 显示文件系统 inode 的使用信息#
默认情况下,df 命令汇总可用和已用的磁盘空间。你可以通过传递 -i
或 --inodes
选项来接收有关可用和已使用的 inode 报告。
# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
udev 2032387 398 2031989 1% /dev
tmpfs 2037595 1224 2036371 1% /run
/dev/vda1 3276800 325180 2951620 10% /
tmpfs 2037595 7 2037588 1% /dev/shm
tmpfs 2037595 4 2037591 1% /run/lock
tmpfs 2037595 16 2037579 1% /sys/fs/cgroup
overlay 3276800 325180 2951620 10% /var/lib/docker/overlay2/c1955f95c338497d2f669ee0baf2706f93c2765001cafd3568b5af9ebfbe0dfd/merged
overlay 3276800 325180 2951620 10% /var/lib/docker/overlay2/85a6ee4a64760a9e52efa312094092121160030132aaaf4bd32ecf5585324dfd/merged
overlay 3276800 325180 2951620 10% /var/lib/docker/overlay2/692ed70766a4ee954c0f0f1b19d69b906c33ae54a618f8686f66e31e9ac05606/merged
shm 2037595 1 2037594 1% /var/lib/docker/containers/2a09d78972ebb74a7631dfd5e567a2b54282886ac8d8dc54dc1f5badffc692b8/mounts/shm
shm 2037595 1 2037594 1% /var/lib/docker/containers/fd9619309707c1026876a401ac22eaf8dd9bfbaceb237ee927017818a6ffa3ff/mounts/shm
shm 2037595 1 2037594 1% /var/lib/docker/containers/080d0d79e069041a2997dfaf2c07e69a0518ad44271dad4688f459958dac09c5/mounts/shm
tmpfs 2037595 4 2037591 1% /run/user/1000
如果分区包含很多小文件,这些信息可能会有帮助,这可能会比耗尽可用磁盘空间更快的耗尽可用的 inode。
d. 列出文件系统超级块的信息#
你可以使用 tune2fs -l
命令来显示所有与 inode 相关的信息。
# tune2fs -l /dev/vda1 | grep inode
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent sparse_super large_file uninit_bg
Free inodes: 2952348
First inode: 11
Journal inode: 8
First orphan inode: 221187
Journal backup: inode blocks
目录的 inode 结构#
上面提到过,Linux 中的目录也被视为文件。目录是将文件名映射到其 inode number 的特殊文件 (此映射称为 dentry)。因此,当我们说某个目录包含文件和其他目录时,我们的意思是该目录将这些文件和目录映射到它们的 inode number。这就是目录无法容纳两个具有相同名称的文件的原因,因为它无法使用两个不同的 inode number 映射一个名称。
当一个文件通过其父目录映射到它到 inode 时,那么最顶层的目录 (即 / 目录) 如何映射到它的 inode?实际上,/ 目录的 inode number 是固定的,始终为 2。
# stat /
File: '/'
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: fd01h/64769d Inode: 2 Links: 24
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-07-24 17:05:52.740982553 +0800
Modify: 2018-12-21 18:02:05.258315357 +0800
Change: 2018-12-21 18:02:05.258315357 +0800
Birth: -
链接#
在命令 ls -l
的输出中,权限之后和所有者之前的列是链接计数。 链接计数是指文件的硬链接数。 要理解硬链接,我们从链接开始。 链接是指向另一个文件的指针。 在 Linux 世界中,存在两种类型的链接:
a. 符号链接 (软链接)#
符号链接是一个单独的文件,其内容指向被链接的文件。 要创建符号链接,请使用带有 - s 选项的 ln 命令。 使用 ln 命令时,请确保首先引用原始文件的名称,然后引用要创建的链接的名称。
# ln -s /home/opt/sync.sh filesync
这里 filesync 是 sync.sh 的符号链接。 把它想象成一个快捷方式。 编辑 filesync 就像直接编辑原始文件一样。 如果我们删除或移动原始文件,链接将被破坏,我们的 filesync 文件将不再可用。
ls -l
命令显示生成的文件是符号链接。 这由 ls -l
输出的第一个位置中的字母 l 以及列表末尾的箭头指示,该箭头表示链接所指向的文件。
# ls -l filesync
lrwxrwxrwx 1 root root 20 Apr 7 06:08 filesync -> /home/opt/sync.sh
比较符号链接和原始文件时,您会发现它们之间存在明显差异。
# ls -il /home/opt/sync.sh filesync
258674 lrwxrwxrwx 1 root root 20 Apr 7 06:08 filesync -> /home/opt/sync.sh
517333 -rw-r----- 1 root root 5 Apr 7 06:09 /home/opt/sync.sh
原始文件只是一个直接连接到 inode 的文件,而符号链接指向该文件。 符号链接的大小是它引用的文件名称的字节数,因为符号链接中没有其他信息可用。
b. 硬链接#
要了解硬链接是什么,关键是要了解文件的标识是其 inode 编号,而不是其名称。 硬链接是一个引用 inode 的名称。 这意味着如果 file1 有一个名为 file2 的硬链接,那么这两个文件都引用相同的 inode。 因此,当您为文件创建硬链接时,您真正要做的就是为 inode 添加一个新名称。 为此,请使用不带选项的 ln 命令。
# ls -l /home/opt/sync.sh
-rw-r----- 1 root root 5 Apr 7 06:09 /home/bobbin/sync.sh
# ln /home/opt/sync.sh synchro
让我们来比较这两个文件
# ls -il /home/bobbin/sync.sh synchro
517333 -rw-r----- 2 root root 5 Apr 7 06:09 /home/opt/sync.sh
517333 -rw-r----- 2 root root 5 Apr 7 06:09 synchro
关于硬链接的有趣之处在于原始文件和链接之间没有区别:它们只是连接到同一个 inode 的两个名称。
正如您必须注意到的,与软链接不同,硬链接不是特殊文件。 现在,链接计数是文件硬链接的数字。 因此,创建硬链接后链接计数会增加,如上图所示。 这些硬链接有两个限制:
- 目录不能硬链接。 Linux 不允许这样做以维护目录的非循环树结构。
- 无法跨文件系统创建硬链接。 这两个文件必须位于相同的文件系统上,因为不同的文件系统具有不同的独立 inode 表(不同文件系统上具有相同 inode 编号的两个文件是不同的)。
结论#
每个 Linux 文件都有一个 inode 数据结构,inode 包含文件的所有属性,但不包含文件名。 符号链接类似于指向原始文件的快捷方式,而硬链接类似于文件的一份拷贝。 原始文件和硬链接之间没有区别,他们都引用同一个 inode。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: