如何在Unix文件系统中实现目录?


19

我的问题是目录如何实现?我可以相信像表,数组或类似变量这样的数据结构。由于UNIX是开放源代码,因此我可以在源代码中查看程序在创建新目录时的功能。您能告诉我该主题的内容吗?目录“是”我可以理解的文件,并且目录真的是文件吗?我不确定文件是否确实存储在“文件中”,而您仍然可以说出关于几乎所有内容的word文件,我不确定这绝对不是文件,因为您甚至可以将变量称为a文件。例如,链接当然不是文件,而链接就像目录,但是这违反了目录是文件?


1
您对任何特定的文件系统感兴趣吗?
伊格纳西奥·巴斯克斯

3
在UNIX中,所有内容都是文件(历史性的知识)。但是,并非每个UNIX都是开源的。Gnu的不是Unix,您知道吗?Open Solaris是一个开源Unix,而Linux只是一个unixoid操作系统。:)是的-文件系统-Reiserfs?Ext2-3-4?XFS?NFS?
用户未知,

2
链接实际上是一个文件,太。
mattdm 2011年

5
一个符号链接是一个文件。硬链接是文件系统图中的一条边。
dmckee

3
广告:您可能对操作系统开发站点建议感兴趣。
吉尔斯(Gilles)'所以

Answers:


22

目录的内部结构取决于使用的文件系统。如果您想确切地了解会发生什么,请查看文件系统实现。

基本上,在大多数文件系统中,目录是文件名(键)和索引节点数字(值)之间的关联数组。这样的东西¹:

1167010 .
1158721 ..
1167626 subdir
 132651 barfile
 132650 bazfile

此列表在(通常)4KB块链内以某种或多或少有效的方式编码。请注意,常规文件的内容以类似的方式存储。对于目录,没有必要知道这些块中实际使用的大小。因此,报告的目录大小du是4KB的倍数。

索引节点在那里将块连接在一起,形成单个实体,即一般意义上的“文件”。它们由一个数字标识,该数字是某种地址,通常每个地址都存储为一个特殊的块。

所有这些的管理都在内核模式下进行。软件只是要求创建一个带有int mkdir(const char *pathname, mode_t mode);导致系统调用的函数的目录,其余所有操作都在后台执行。

关于链接结构:

硬链接不是文件,它只是一个新目录条目(即名称-索引节点编号关联),它指向一个预先存在的索引节点实体²。这意味着可以从不同的路径名访问同一索引节点。特别是,由于元数据(权限,所有权,时间戳等)存储在索引节点中,因此它们是唯一的,并且与选择用于访问文件的路径名无关。

符号链接一个文件,与目标不同。这意味着它具有自己的inode。过去,它的处理方式就像普通文件一样:目标路径存储在数据块中。但是现在,出于效率原因,在最近的ext文件系统中,短于60字节长的路径存储在inode自身内(使用通常用于存储指向数据块的指针的字段)。


1.这是使用获得的ls -ai1 testdir
2.如今其类型必须与“目录”不同。


感谢您的详细说明,以便我可以从编程的角度理解目录和文件之间的区别。
尼古拉斯

12

为了扩展来自StéphaneGimenez的帖子,创建新目录的过程是使用st_mode值为S_IFDIR(具有权限模式)创建新的inode,并在具有链接的新inode的第一个数据块中创建两个条目( 2)系统调用:“。” 指向这个新的索引节点,“ ..”指向父目录,然后在父目录中创建一个带有索引节点和新目录名称的条目-第一部分和最后一部分由系统调用mknod( 2)。而且,这些天只有root用户可以使用mknod(2)来执行我们正在谈论的任务。

例如,mkdir("/home/larry.user/xyzzy", 0666)基本上是以下内容(这是SysV days [1]中的C代码):

int mode = 0666;
char newdir[] = "/home/larry.user/xyzzy";
char path1[NAMESZ+4, path2[NAMESZ+4], *p;
mknod(newdir, S_IFDIR|mode);
strcpy(path1, newdir);
strcat(path1, "/."); /* "." link */
link(newdir, path1);
strcat(path1, ".");  /* ".." link */
strcpy(path2, newdir);
if ((p = strrchr(path2, '/') == (char *)0) /* root directory */
    link(".", path1);
else {
    *p = '\0';
    link(path2, path1);
}
  1. Haviland&Salama,“ UNIX系统编程”,1987,pp69-71。

这太容易出错(也是fsck的主要原因之一),因此创建了mkdir(2)系统调用来为您执行此操作。

请注意,可以使用mknod(2)创建amy文件系统对象:常规文件,目录,设备文件,符号链接等。因此要回答OP的问题之一,是的,目录是文件,这意味着“是一个由索引节点表示的对象,该对象驻留在具有I / O接口行为的文件系统中”。


感谢您的非常有趣的回答。我理解并认为我也可以查看该程序的源代码,该程序touch将创建一个空文件并查看其作用。
Niklas

2

如果您想了解有关Unix / Linux文件系统的更多信息,我建议您阅读两本书《了解Linux内核》《 Linux内核开发》。这些是了解Linux内核的最佳书。

在“公共文件模型” Unix系统中,每个目录都被视为一个文件,其中包含文件和目录的列表。

在VFS(虚拟文件系统)中,目录以称为的结构表示dentry。的dentry 是C结构是字符串名(d_name),一个指向一个inode(d_inode)和一个指向父目录项(d_parent)。索引节点是一种用于处理有关文件系统中文件信息的结构。例如,如果您有目录/tmp/test/foo,则VFS将为路径名中的每个组件创建一个dentry对象。这样,它将为创建一个dentry对象/,第二个dentry对象用于test输入根目录,第三个dentry对象用于foo测试目录。


谢谢迪米特里。我想了解为什么某些项目选择特定的数据结构,例如B树,二叉树,特里树或关联数组。我认为选择合适的数据结构/数据模型很重要。了解不同的实现将提供我正在寻找的详细信息。
尼古拉斯

1

您可以先阅读http://www.freebsd.org/doc/zh/books/design-44bsd/book.html#OVERVIEW-FILESYSTEM。有关更多详细信息,请阅读经典经典书籍“ 4.4 BSD操作系统的设计和实现”。


感谢您的链接。我知道这两个文件都是目录,基本上都是将数组解释为文件或目录的数组。如果我错了,请指正我
。.– Niklas

1
目录在传统上只是经过特殊格式化的文件,但现在不再如此:en.wikipedia.org/wiki/ReiserFS#Design 在ReiserFS和其他一些目录中,目录是数据库中的条目。目录可以充当数组,但这仅仅是编程的抽象。
Bruce Ediger

非常感谢您指出细节。现在,我想我更了解文件系统的工作原理,仍然想知道程序如何以及为什么locate起作用,以及这与通过运行来更新定位程序有关updatedb(请指定我使用PC-BSD,DragonflyBSD和Ubuntu Natty从Live CD引导并对不同安装进行基准测试)和接口)
Niklas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.