4

我已经看到很多解释为什么在基于 Unix 的操作系统中空目录的链接计数是 2 而不是 1。他们都说这是因为 '.' 目录,每个目录都指向自己。我明白为什么会有一些“。”的概念。对于指定相对路径很有用,但是通过在文件系统级别实现它可以获得什么?为什么不让 shell 或采用路径的系统调用知道如何解释它?

'..' 是一个真正的链接对我来说更有意义——文件系统需要存储一个指向父目录的指针才能导航到它。但我不明白为什么'。成为一个真正的链接是必要的。它似乎也导致了实现中的一个丑陋的特殊情况——你会认为你只能释放链接数小于 1 的 inode 使用的空间,但如果它们是目录,你实际上需要检查一个链接数少于2。为什么不一致?

4

2 回答 2

2

为什么不让 shell 或采用路径的系统调用知道如何解释它?

为了透明度。如果文件系统这样做,应用程序(以及无数系统调用)不必对“。”做任何特别的事情。比如“哦,用户想要当前目录!”。的概念cwd和它的含义都整齐地存储在 FS 级别。

它似乎也导致了实现中的一个丑陋的特殊情况——你会认为你只能释放链接数小于 1 的 inode 使用的空间,但如果它们是目录,你实际上需要检查链接数小于 2。

这不是特例。Unix 中的所有文件都有许多链接。您检查过的任何文件unlink“这是最后一个链接吗?”。如果是,它会得到印章。如果没有,它会徘徊。

于 2011-10-14T04:16:48.480 回答
1

(嗯:以下现在有点史诗......)

unix 文件系统上的目录设计(为了迂腐,通常但不一定附加到 unix 操作系统)上的目录设计代表了一种奇妙的洞察力,它实际上减少了所需的特殊情况的数量。

“目录”实际上只是文件系统中的一个文件。文件系统中文件的所有实际内容都在inode中(从您的问题中,我可以看到您已经知道其中的一些内容)。磁盘上的 inode 没有结构——它们只是一大堆带编号的字节块,像花生酱一样散布在磁盘上。这没有用,而且确实对任何有一点整洁头脑的人来说都是排斥的。

唯一特殊的inode 是 inode 编号 2(不是 0 或 1,出于传统原因);inode 2 是一个目录文件:根目录。当系统挂载文件系统时,它“知道”它必须读取 inode 2,才能启动自己。

目录文件只是一个文件,具有旨在由 opendir(3) 和朋友读取的内部结构。您可以在 dir(5) 中看到其内部结构(取决于您的操作系统);如果你看一下,你会发现目录文件条目几乎不包含有关文件的信息——这些都在文件 inode 中。该文件的几个特别之处之一是,如果您尝试以允许写入的模式打开目录文件,open(2) 函数将给出错误。各种其他命令(仅举一个例子,hexdump)将拒绝以正常方式处理目录文件,只是因为这可能不是您想要做的(但这是他们的特殊情况,而不是文件系统的)。

硬链接只不过是目录文件映射中的一个条目。您可以在这样的映射中有两个(或更多)条目,它们都映射到相同的 inode 编号:因此该 inode 有两个(或更多)硬链接。这也解释了为什么每个文件都至少有一个“硬链接”。inode 有一个引用计数,它记录在文件系统某处的目录文件中提到该 inode 的次数(这是您在执行时看到的数字ls -l)。

好的:我们现在进入正题。

目录文件是字符串(“文件名”)到数字(inode 编号)的映射。这些 inode 编号是“在”该目录中的文件的 inode 编号。该目录中的文件可能包括其他目录文件,因此它们的 inode 编号将在目录中列出的那些中。因此,如果您有一个 file /tmp/foo/bar,那么目录文件foo包含一个 for 的条目bar,将该字符串映射到该文件的 inode。目录文件中还有一个条目/tmp,用于在目录中的目录foo文件/tmp

当您使用 mkdir(2) 创建目录时,该函数

  1. 创建具有正确内部结构的目录文件(带有一些 inode 编号),
  2. 向父目录添加一个条目,将新目录的名称映射到这个新的 inode(占其中一个链接),
  3. 向新目录添加一个条目,映射字符串 '.' 到同一个inode(这说明了另一个链接),并且
  4. 将另一个条目添加到新目录,将字符串“..”映射到它在步骤 (2) 中修改的目录文件的 inode(这说明您将在包含子目录的目录文件上看到更多的硬链接)。

最终结果是(几乎)唯一的特殊情况是:

  • open(2) 函数试图通过阻止您打开目录文件进行写入来使自己更难开枪。
  • mkdir(2) 函数通过向新目录文件添加几个额外的条目('.' 和 '..')使事情变得简单而简单,纯粹是为了方便在文件系统中移动。我怀疑没有'.'文件系统会很好地工作。和'..',但使用起来会很痛苦。
  • 目录文件是少数几种被标记为“特殊”的文件类型之一——这实际上是告诉诸如 open(2) 之类的东西的行为略有不同的原因。见st_modestat(2)。
于 2011-10-14T19:56:09.203 回答