我看过很多关于为什么基于 Unix 的操作系统中空目录的链接计数是 2 而不是 1 的解释。他们都说这是因为“.”。目录,每个目录都指向其自身。我理解为什么有一些“.”的概念对于指定相对路径很有用,但是在文件系统级别实现它会得到什么?为什么不让 shell 或采用路径的系统调用知道如何解释它呢?
“..”是一个真正的链接,对我来说更有意义——文件系统需要存储一个指向父目录的指针才能导航到它。但我不明白为什么'。'成为真正的链接是必要的。这似乎也导致了实现中一个丑陋的特殊情况——你会认为你只能释放链接计数小于 1 的 inode 使用的空间,但如果它们是目录,你实际上需要检查链接数小于2。为什么不一致?
答案1
确实是一个有趣的问题。乍一看,我看到了以下优点:
首先,您声明.
可以通过 Shell 或系统调用将“”解释为当前目录。但在目录中使用点输入实际上消除了这种必要性,并强制在更低级别保持一致性。
但我不认为这是这个设计决策背后的基本思想。
当在目录中创建或删除文件时,目录的修改时间戳也必须更新。该时间戳存储在其索引节点中。索引节点号存储在相应的目录项中。
如果点条目不会在那里,例程必须在父目录中搜索该目录的条目处的索引节点号,这将导致再次进行目录搜索。
但幸运的是,当前目录中有点条目。在当前目录中添加或删除文件的例程只需跳回到第一个条目(点条目通常所在的位置)并立即找到当前目录的索引节点号。
关于点输入还有第三个好处:
当fsck
检查损坏的文件系统并且必须处理也不在空闲列表上的非连接块时,很容易验证数据块(当解释为目录列表时)是否具有指向 inode 的点条目它又指向这个数据块。如果是这样,则该数据块可以被视为丢失的目录,必须重新连接。
答案2
(嗯:下面的内容现在有点史诗般的了......)
unix 文件系统上目录的设计(迂腐地说,是通常但不一定附属于 unix 操作系统)代表了一种奇妙的洞察力,它实际上减少了所需的特殊情况的数量。
“目录”实际上只是文件系统中的一个文件。文件系统中文件的所有实际内容都位于索引节点(从你的问题中,我可以看出你已经知道其中的一些内容)。磁盘上的索引节点没有任何结构——它们只是一大堆编号的字节块,像花生酱一样散布在磁盘上。这没有任何用处,而且确实让任何有一丝整洁意识的人都感到厌恶。
这仅有的特殊 inode 是 inode 编号 2(不是 0 或 1,出于传统原因); inode 2 是一个目录文件:根目录。当系统安装文件系统时,它“知道”它必须读取dir inode 2,才能启动。
目录文件只是一个文件,具有供 opendir(3) 和朋友读取的内部结构。您可以在 dir(5) 中看到其内部结构(取决于您的操作系统);如果你看一下,你会发现目录文件条目几乎不包含有关该文件的信息——所有这些都在文件 inode 中。该文件的几个特殊之处之一是,如果您尝试使用允许写入的模式打开目录文件,则 open(2) 函数将给出错误。各种其他命令(仅举一个例子,hexdump
)将拒绝以正常方式处理目录文件,只是因为这可能不是您想要做的(但这是它们的特殊情况,而不是文件系统的)。
A硬链接只不过是目录文件映射中的一个条目。在这样的映射中可以有两个(或更多)条目,它们都映射到相同的索引节点号:因此该索引节点有两个(或更多)硬链接。这也解释了为什么每一个文件至少有一个“硬链接”。 inode 有一个引用计数,它记录文件系统中某个目录文件中提及该 inode 的次数(这是您在执行操作时看到的数字ls -l
)。
好的:我们现在进入正题了。
目录文件是字符串(“文件名”)到数字(索引节点号)的映射。这些索引节点号是该目录“中”的文件的索引节点号。该目录“中”的文件可能包括其他目录文件,因此它们的索引节点号将在目录中列出的索引节点号中。因此,如果您有一个 file /tmp/foo/bar
,则目录 filefoo
包含一个 条目bar
,将该字符串映射到该文件的索引节点。目录文件中还有一个条目,用于目录“中”的/tmp
目录文件。foo
/tmp
当您使用 mkdir(2) 创建目录时,该函数
- 创建一个具有正确内部结构的目录文件(带有一些索引节点号),
- 向父目录添加一个条目,将新目录的名称映射到这个新 inode(占链接之一),
- 向新目录添加一个条目,映射字符串“.”到同一个索引节点(这说明了另一个链接),并且
- 向新目录添加另一个条目,将字符串“..”映射到在步骤 (2) 中修改的目录文件的 inode(这说明您将在包含子目录的目录文件上看到大量硬链接) )。
最终结果是(几乎)唯一的特殊情况是:
- open(2) 函数试图通过阻止您打开目录文件进行写入来让您更难搬起石头砸自己的脚。
- mkdir(2) 函数通过向新目录文件添加几个额外的条目(“.”和“..”)使事情变得美好而简单,纯粹是为了方便在文件系统中移动。我怀疑文件系统在没有“.”的情况下也能正常工作。和“..”,但使用起来会很痛苦。
- 目录文件是少数被标记为“特殊”的文件类型之一——这实际上是告诉 open(2) 之类的东西的行为略有不同。参见
st_mode
统计数据(2)。
(从stackoverflow原始问题复制过来,2011-10-20)