您想知道的关于Linux上的inode的所有信息

Linux文件系统依赖于inode。文件系统内部工作的这些重要部分经常被误解。让我们来看看它们到底是什么,以及它们是做什么的。

文件系统的元素

根据定义,文件系统需要存储文件,并且它们还包含目录。这些文件存储在目录中,并且这些目录可以有子目录。在某些地方,必须记录所有文件在文件系统中的位置、它们的名称、它们属于哪些帐户、它们拥有哪些权限等等。此信息称为元数据,因为它是描述其他数据的数据。

在Linux ext4文件系统中,索引节点和目录结构可以协同工作,以提供存储每个文件和目录的所有元数据的基础框架。它们使需要元数据的任何人都可以使用元数据,无论是内核、用户应用程序还是Linux实用程序(如ls、stat和df)。

信息节点和文件系统大小

虽然确实有一对结构,但文件系统需要的远不止这些。每种结构都有成千上万个。每个文件和目录都需要一个inode,并且因为每个文件都在一个目录中,所以每个文件也需要一个目录结构。目录结构也称为目录条目或“dentry”。

每个inode都有一个inode编号,该编号在文件系统中是唯一的。相同的信息节点号可能出现在多个文件系统中。但是,无论您的Linux系统上装载了多少个文件系统,文件系统ID和信息节点编号组合在一起都是唯一的标识符。

请记住,在Linux中,您不需要挂载硬盘驱动器或分区。您挂载了分区上的文件系统,因此很容易在没有意识到的情况下拥有多个文件系统。如果单个驱动器上有多个硬盘或分区,则您有多个文件系统。它们可能是相同的类型-例如,都是ext4-但它们仍然是不同的文件系统。

所有inode都保存在一个表中。使用索引节点编号,文件系统可以轻松地计算出该索引节点所在的索引节点表中的偏移量。您可以看到为什么inode中的“i”代表索引。

包含inode编号的变量在源代码中声明为32位无符号长整型。这意味着inode编号是一个最大大小为2^32的整数值,计算结果为4,294,967,295个-远远超过40亿个inode。

这是理论上的最大值。实际上,ext4文件系统中的inode数量是在以每16 KB文件系统容量一个inode的默认比率创建文件系统时确定的。目录结构是在使用文件系统时动态创建的,因为文件系统中创建了文件和目录。

有一个命令可以用来查看您的计算机上的文件系统中有多少inode。df命令的-i(Inode)选项指示它以inode数量显示其输出。

我们将查看第一个硬盘驱动器上第一个分区上的文件系统,因此我们键入以下内容:

df -i /dev/sda1

输出结果为我们提供了以下信息:

文件系统:报告的文件系统。 inode:此文件系统中的inode总数。 Ised:正在使用的信息节点数。 IFree:可供使用的剩余信息节点数。 Iuse%:已使用的inode的百分比。 已装载于:此文件系统的装载点。

我们已经使用了此文件系统中10%的inode。文件以磁盘块的形式存储在硬盘上。每个inode指向存储其表示的文件内容的磁盘块。如果您有数百万个小文件,您可以在硬盘空间用完之前用完inode。然而,这是一个很难遇到的问题。

在过去,一些将电子邮件消息存储为离散文件(这会迅速导致大量小文件集合)的邮件服务器存在此问题。不过,当这些应用程序将其后端改为数据库时,问题就解决了。一般的主系统不会用完inode,这很好,因为使用ext4文件系统时,如果不重新安装文件系统,您就无法添加更多的inode。

要查看文件系统上磁盘块的大小,可以使用带有--getbsz(获取块大小)选项的block dev命令:

sudo blockdev --getbsz /dev/sda

块大小为4096字节。

让我们使用-B(块大小)选项将块大小指定为4096字节,并检查常规磁盘使用情况:

df -B 4096 /dev/sda1

此输出向我们显示:

文件系统:我们报告的文件系统。 4K块:此文件系统中4KB块的总数。 已用:正在使用的4K块的数量。 可用:可供使用的剩余4 KB数据块数量。 Use%:已使用的4 KB数据块的百分比。 已装载于:此文件系统的装载点。

在我们的示例中,文件存储(以及inode和目录结构的存储)使用了该文件系统上28%的空间,而代价是10%的inode,所以我们状态良好。

信息节点元数据

要查看文件的inode编号,我们可以使用带有-i(Inode)选项的ls:

ls -i geek.txt

此文件的inode编号为1441801,因此此inode保存此文件的元数据,并且传统上保存指向文件驻留在硬盘驱动器上的磁盘块的指针。如果文件是碎片文件、非常大的文件或两者兼而有之,则信息节点所指向的某些块可能包含指向其他磁盘块的更多指针。此外,这些其他磁盘块中的一些也可能包含指向另一组磁盘块的指针。这克服了inode是固定大小并且能够容纳有限数量的指向磁盘块的指针的问题。

这种方法被一种利用“范围”的新方案所取代。它们记录用于存储文件的每组连续块的开始块和结束块。如果文件未进行碎片整理,则只需存储第一个数据块和文件长度。如果文件是碎片文件,则必须存储文件每个部分的第一个和最后一个块。这个方法(显然)更有效率。

如果您想查看您的文件系统是否使用磁盘块指针或区段,可以查看inode内部。为此,我们将使用带-R(请求)选项的debugfs命令,并将感兴趣的文件的inode传递给它。这要求调试文件系统使用其内部的“stat”命令来显示inode的内容。因为inode编号在文件系统中是唯一的,所以我们还必须告诉debugf该inode所在的文件系统。

下面是此示例命令的外观:

sudo debugfs -R "stat <1441801>" /dev/sda1

如下所示,debugfs命令从inode提取信息,并以更少的篇幅将其呈现给我们:

我们看到了以下信息:

inode:我们正在查看的inode的编号。 类型:这是一个常规文件,不是目录或符号链接。 模式:文件权限,以八进制表示。 标志:表示不同特性或功能的指示器。0x80000是“EXTENTS”标志(下面将详细介绍)。 生成:当有人通过网络连接访问远程文件系统时,网络文件系统(NFS)会使用此功能,就像它们装载在本地计算机上一样。索引节点和代号用作文件句柄的一种形式。 版本:信息节点版本。 用户:文件的所有者。 组:文件的组所有者。 项目:应始终为零。 Size:文件的大小。 文件ACL:文件访问控制列表。这些设置旨在允许您对不在所有者组中的人员提供有控制的访问权限。 链接:指向文件的硬链接数。 BlockCount:分配给此文件的硬盘空间大小,以512字节的区块为单位。我们的文件已经分配了其中的8个,即4096字节。因此,我们的98字节文件位于单个4096字节的磁盘块中。 碎片:此文件未碎片。(这是一个过时的标志。)。 ctime:创建文件的时间。 时间:上次访问此文件的时间。 mtime:上次修改此文件的时间。 CrTime:创建文件的时间。 额外inode字段的大小:ext4文件系统引入了在格式化时分配更大的磁盘inode的能力。该值是inode正在使用的额外字节数。这一额外空间还可用于满足未来对新内核的需求或存储扩展属性。 inode校验和:此inode的校验和,这使得检测inode是否损坏成为可能。 区段:如果正在使用区段(在ext4上,默认情况下是区段),那么关于文件的磁盘块使用情况的元数据有两个数字,表示碎片文件的每个部分的开始块和结束块。这比存储文件的每个部分占用的每个磁盘块效率更高。我们有一个区,因为我们的小文件位于该块偏移量的一个磁盘块中。

文件名在哪里?

我们现在有很多关于该文件的信息,但是,正如您可能已经注意到的,我们没有获得文件名。这就是目录结构发挥作用的地方。在Linux中,就像文件一样,目录也有一个inode。不过,目录inode指向的不是包含文件数据的磁盘块,而是包含目录结构的磁盘块。

与inode相比,目录结构包含关于文件的有限数量的信息。它只保存文件的inode编号、名称和名称长度。

inode和目录结构包含您(或应用程序)需要了解的有关文件或目录的所有信息。目录结构位于目录磁盘块中,因此我们知道文件所在的目录。目录结构为我们提供了文件名和索引节点号。inode告诉我们有关该文件的所有其他信息,包括时间戳、权限以及在文件系统中的何处可以找到文件数据。

目录索引节点

您可以像查看文件的索引节点号一样轻松地查看目录的inode编号。

在以下示例中,我们将使用带有-l(长格式)、-i(索引节点)和-d(目录)选项的ls,并查看工作目录:

ls -lid work/

因为我们使用了-d(目录)选项,所以所有的报告都是关于目录本身的,而不是关于其内容的。此目录的inode为1443016。

要对主目录重复此操作,我们键入以下内容:

ls -lid ~

主目录的inode是1447510,工作目录在主目录中。现在,让我们看看工作目录的内容。我们将不使用-d(目录)选项,而使用-a(All)选项。这将向我们显示通常隐藏的目录条目。

我们键入以下内容:

ls -lia work/

因为我们使用了-a(All)选项,所以单个-(.)。和双点(..)。将显示条目。这些条目表示目录本身(单点)及其父目录(双点。)

如果您查看单点条目的inode编号,您会发现它是1443016-与我们发现工作目录的inode编号时获得的inode编号相同。此外,双点条目的索引节点编号与主目录的索引节点编号相同。

这就是为什么你可以用这张CD..。命令在目录树中上移一级。同样,当您在应用程序或脚本名称前面加上“./”时,您会让shell知道从哪里启动应用程序或脚本。

信息节点和链接

正如我们已经介绍过的,在文件系统中拥有格式良好且可访问的文件需要三个组件:文件、目录结构和索引节点。文件是存储在硬盘上的数据,目录结构包含文件名及其索引节点号,索引节点包含文件的所有元数据。

符号链接是看起来像文件的文件系统条目,但它们实际上是指向现有文件或目录的快捷方式。让我们看看他们是如何管理这一点的,以及如何使用这三个要素来实现这一点。

假设我们有一个目录,其中包含两个文件:一个是脚本,另一个是应用程序,如下所示。

我们可以使用ln命令和-s(符号)选项来创建指向脚本文件的软链接,如下所示:

ls -s my_script geek.sh

我们已经创建了一个指向my_script.sh的名为geek.sh的链接。我们可以键入以下内容并使用工具来查看这两个脚本文件:

ls-li*.sh

geek.sh的条目显示为蓝色。权限标志的第一个字符是代表链接的“l”,并且->指向my_script.sh。所有这些都表明geek.sh是一个链接。

正如您可能预期的那样,这两个脚本文件具有不同的inode编号。然而,可能更令人惊讶的是,软链接geek.sh没有与原始脚本文件相同的用户权限。事实上,geek.sh的权限要自由得多-所有用户都拥有完全权限。

sh的目录结构包含链接的名称及其索引节点。当您尝试使用该链接时,它的inode会被引用,就像常规文件一样。链接索引节点将指向磁盘块,但磁盘块包含原始文件的名称,而不是包含文件内容数据。文件系统重定向到原始文件。

我们将删除原始文件,然后看看当我们键入以下命令查看.geek.sh的内容时会发生什么:

rm my_script.shcat geek.sh

符号链接断开,重定向失败。

我们现在键入以下内容以创建指向应用程序文件的硬链接:

ln special-app geek-app

要查看这两个文件的信息节点,我们键入以下内容:

ls -li

这两个文件看起来都像普通文件。关于geek-app没有任何迹象表明它是ls为geek.sh列出的链接。此外,极客应用程序与原始文件具有相同的用户权限。然而,可能令人惊讶的是,这两个应用程序具有相同的inode编号:1441797。

geek-app的目录条目包含名称“geek-app”和一个inode编号,但它与原始文件的inode编号相同。因此,我们有两个名称不同的文件系统条目,它们都指向相同的inode。事实上,任意数量的项都可以指向相同的inode。

我们将键入以下内容并使用stat程序查看目标文件:

stat special-app

我们看到有两个硬链接指向此文件。它存储在inode中。

在下面的示例中,我们删除原始文件,并尝试使用具有保密、安全密码的链接:

rm special-app./geek-app correcthorsebatterystaple

令人惊讶的是,应用程序按预期运行,但如何运行呢?它之所以有效,是因为当您删除文件时,索引节点可以自由重用。目录结构被标记为索引节点号为零,然后磁盘块可供另一个文件存储在该空间中。

但是,如果指向索引节点的硬链接数大于1,则硬链接计数减1,并且已删除文件的目录结构的索引节点号设置为零。硬盘驱动器和信息节点上的文件内容仍可用于现有的硬链接。

我们将键入以下内容并再次使用stat-这次是在geek-app上:

stat geek-app

这些详细信息是从与前面的STAT命令相同的inode(1441797)中提取的。链接计数减少了1。

因为我们只剩下一个指向此inode的硬链接,如果我们删除geek-app,它将真正删除该文件。文件系统将释放索引节点,并将目录结构标记为索引节点为零。然后,新文件可以覆盖硬盘上的数据存储。

相关:如何在Linux上使用stat命令

信息节点开销

这是一个整洁的系统,但也有开销。要读取文件,文件系统必须完成以下所有操作:

找到正确的目录结构。 读取索引节点编号。 查找正确的信息节点。 读取索引节点信息。 跟随信息节点链接或扩展区到达相关磁盘块。 读取文件数据

如果数据不是连续的,则需要更多的跳转。

想象一下,为执行多个文件的长格式文件列表,olls需要做的工作有多大。为了获得生成其输出所需的信息,ls需要进行大量的来回操作。

当然,加速文件系统访问是Linux尝试尽可能多地进行抢占式文件缓存的原因。“这非常有帮助,但有时-就像任何文件系统一样-开销可能会很明显。

现在你就知道为什么了。

相关文章