(嗯:以下内容是史诗般的...)
UNIX文件系统上的目录设计(通常是,但不一定附加到UNIX OS)是一个很好的见解,实际上减少了所需的特殊情况。
“目录”实际上只是文件系统中的一个文件。文件系统中文件的所有实际内容都以inode为单位(从您的问题中,我可以看到您已经知道其中的某些内容)。磁盘上的inode没有结构-它们只是一大堆带编号的字节blob,像花生酱一样散布在磁盘上。这是没有用的,并且确实对那些有整洁思想的人来说是排斥的。
的唯一的特殊的inode是inode编号2(不是0或1,为传统的原因); inode 2是一个目录文件:根目录。当系统挂载文件系统时,它“知道”它必须读取dir inode 2才能启动。
目录文件只是具有内部结构的文件,旨在供opendir(3)和朋友读取。您可以在dir(5)中看到其内部结构(取决于您的操作系统);如果您看一下,您会发现目录文件条目几乎不包含有关文件的信息-全部在文件inode中。关于此文件的一些特殊之处之一是,如果您尝试使用允许写入的模式打开目录文件,则open(2)函数将给出错误。其他各种命令(仅举一个例子hexdump
)将拒绝以正常方式对目录文件执行操作,只是因为这可能不是您想要执行的操作(但这是它们的特殊情况,而不是文件系统)。
一个硬链接是什么多也小于在一个目录下的文件的映射中的条目。您可以在这样的映射中有两个(或更多)条目,它们都映射到相同的inode编号:因此该inode具有两个(或更多)硬链接。这也解释了为什么每个文件至少具有一个“硬链接”。索引节点有一个引用计数,该引用计数记录该索引节点在文件系统中某个目录文件中被提及的次数(这是您在执行操作时看到的数字ls -l
)。
好:我们现在到了重点。
目录文件是字符串(“文件名”)到数字(索引节点号)的映射。这些索引节点号是该目录中“文件”的索引节点号。该目录“中”的文件可能包括其他目录文件,因此它们的inode编号将在该目录中列出的文件中。因此,如果您有一个file /tmp/foo/bar
,则目录文件foo
包含一个的条目bar
,将该字符串映射到该文件的inode。还有在目录文件中的条目/tmp
,对目录文件foo
是“在”目录/tmp
。
使用mkdir(2)创建目录时,该函数
- 创建具有正确内部结构的目录文件(带有一些inode编号),
- 在父目录中添加一个条目,将新目录的名称映射到这个新的inode(占链接之一),
- 将一个条目添加到新目录,映射字符串“。”。到相同的inode(这占另一个链接),并且
- 在新目录中添加另一个条目,将字符串“ ..”映射到在步骤(2)中修改的目录文件的索引节点(这说明您将在包含子目录的目录文件上看到大量的硬链接)。
最终结果是(几乎)唯一的特殊情况是:
- open(2)函数试图阻止您打开要写入的目录文件,从而使您难以用脚射击。
- mkdir(2)函数通过在新目录文件中添加几个额外的条目(“。”和“ ..”)使事情变得轻松便捷,这仅仅是为了方便在文件系统中移动。我怀疑没有“。”的文件系统是否可以很好地工作。和“ ..”,但使用起来很麻烦。
- 目录文件是标记为“特殊”的几种文件类型之一-这实际上是告诉open(2)这样的行为略有不同的原因。参见
st_mode
stat(2)。
(复制自stackoverflow原始问题,2011-10-20)
..
硬链接,您的树步软件就已经需要具有“不要跟随父目录链接上的循环”的例外,因此除了链接之外,它几乎没有增加任何复杂性.
。