inode 编号是如何分配的

inode 编号是如何分配的

两个已知事实:

  1. 在Linux中,将文件从同一文件系统上的一个位置移动到另一个位置不会更改inode(文件保留在“同一位置”,仅更改涉及的目录)
  2. 然而,复制会生成一个真正的新文件,并带有新的索引节点。

有了这些信息,我观察到以下现象:

$ ls -li /tmp/*.db
1452722 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:33 /tmp/vf4.db
$
$ cp /tmp/vf4.db /tmp/vf4.2.db
$ ls -li /tmp/*.db # New inode introduced
1452719 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:38 /tmp/vf4.2.db
1452722 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:33 /tmp/vf4.db
$
$ mv /tmp/vf4.2.db /tmp/vf4.db
$ ls -li /tmp/*.db
1452719 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:38 /tmp/vf4.db
$
$ cp /tmp/vf4.db /tmp/vf4.2.db
$ ls -li /tmp/*.db # Original inode appears again! (1452722)
1452722 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:41 /tmp/vf4.2.db
1452719 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:41 /tmp/vf4.db
$
$ mv /tmp/vf4.2.db /tmp/vf4.db
$ ls -li /tmp/*.db
1452722 -rw-r--r-- 1 omerda omerda 245760 Jul  7 12:41 /tmp/vf4.db

这种“往返”总是导致原始索引节点再次附加到原始文件。我本希望在每个副本中使用一个全新的索引节点。

它是如何重用相同的索引节点的?

编辑

在评论部分,有些人要求提供背景信息。因此,上下文是一些 sqlite 包装器使用这种不好的做法来替换 db 文件,而 sqlite3 没有显示有关替换的错误。然而,这不是关于 sqlite 的问题,请紧扣主题和问题。

答案1

系统重用相同的索引节点,因为文件系统层选择这样做。正如在一篇文章中提到的评论,这是一个实现细节。在我的例子中,这是ext4,但是不同的文件系统类型没有理由不应该以不同的方式使用(或重用)inode。您可能会发现一个没有 inode 的文件系统,并且 inode 编号是根据请求动态合成的。文件系统tmpfs不会以同样的方式重用索引节点号。

# Create two files on ext4
touch file
cp file copy
ls -li file copy
133235 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:13 copy
129071 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:13 file

# Remove one, copy the other back    
rm file
cp copy file
ls -li file copy
133235 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:13 copy
129071 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:13 file

# Remove one, create an unexpected intervention, copy the other back
rm file
touch thing
cp copy file
ls -li file copy thing
133235 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:13 copy
133237 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:14 file
129071 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:14 thing

现在让我们在tmpfs文件系统上重复一遍,例如/dev/shm

# Create two files on tmpfs
touch file
cp file copy
ls -li file copy
369355 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:27 copy
369354 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:27 file

# Remove one, copy the other back    
rm file
cp copy file
ls -li file copy
369355 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:27 copy
368123 -rw-r--r-- 1 roaima roaima 0 Jul  7 11:28 file

潜在有用的参考

答案2

它是如何重用相同的索引节点的?

在 ext4 中,inode 编号只是包含实际 inode 数据的表的索引。传说这就是“i”的意思,“索引”。它实际上并不是存储为单个连续表,但这并不重要。

您获得的特定 inode 编号恰好是当时空闲的编号,并且文件系统代码确定性地实现选择是有意义的,因此如果它第一次在 1452719 之前选择 1452722,则选择 1452722 是有意义的如果现在免费,并且除了制作副本之外没有进行任何其他更改,请再次进行。它无法为文件的特定化身永久保留 inode 编号,因为这很快会导致文件系统充满为已删除文件保留的不可用 inode 条目。

您不能指望获得特定的索引节点号,主要是因为系统上的某些其他进程可能会同时创建文件,并保留您在重新创建文件之前期望获得的索引节点号。或者其他进程可能会删除文件,导致文件系统代码给出下一个文件。文件系统组织成块组及其关联索引节点的方式也可能意味着简单地增长文件可能会改变文件系统寻找空闲索引节点的位置。或者也可能不会。所有 inode 编号告诉您的是识别该文件现在存在,并且在创建新文件时,您只会得到一个与任何现有文件都不对应的文件。

而且,在其他类型的文件系统(例如 VFAT)上,没有静态 inode 编号,但您可能只会得到一个正在运行的计数器。

答案3

这种“往返”总是导致原始索引节点再次附加到原始文件。

当你说“总是”时,你的意思是“每次我看”。但这绝对是不是有保证的结果!

我本希望在每个副本中使用一个全新的索引节点。

这当然是另一种可能的结果。但由于可用的 inode 编号不是无限的,因此在某些时候您将不得不获得一个可回收的(不是全新的或“新鲜的”)编号。

它是如何重用相同的索引节点的?

任何传统的文件系统都必须管理块的分配。当文件被分配或增长时,必须分配新的块来存储文件的数据。删除文件后,其块可以重新使用。不同的文件系统使用不同的技术来管理“空闲”块集,并将它们分配给文件。所选择的算法显然会对性能和碎片产生很大影响。有时,分配可能看起来是后进先出——也就是说,最近释放的块可能是下一个要分配的块。但显然情况并非总是如此。

而 inode 的情况几乎完全相同。分配文件时,必须分配新的索引节点和/或索引节点号来标识该文件。当文件被删除时,它的索引节点和索引节点号可以重新使用。不同的文件系统使用不同的技术来管理“空闲”索引节点集,并将它们分配给文件。有时,分配可能看起来是后进先出的,但显然情况并非总是如此。

相关内容