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

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

我的问题是目录是如何实现的?我可以相信像变量这样的数据结构,例如表、数组或类似的数据结构。由于 UNIX 是开源的,我可以在源代码中查看程序在创建新目录时执行的操作。您能告诉我在哪里可以查看或详细说明该主题吗?目录“是”我可以理解的文件并且目录真的是文件吗?我不确定文件是否确实存储在“文件中”,但仍然可以用“文件”这个词来表示几乎任何东西,并且我不确定什么绝对不是文件,因为您甚至可以将变量称为“a”文件。例如,链接当然不是文件,链接就像目录,但这违反了目录是文件吗?

答案1

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

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

1167010 .
1158721 ..
1167626 subdir
 132651 barfile
 132650 bazfile

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

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

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

关于链接结构:

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

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


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

答案2

为了扩展 Stéphane Gimenez 的帖子,创建新目录是使用 S_IFDIR(具有权限模式)的 st_mode 值创建新 inode 的过程,并使用链接在新 inode 的第一个数据块中创建两个条目( 2) 系统调用:'.'它指向这个新的 inode 和 '..' 指向父目录,然后使用 inode 和新目录的名称在父目录中创建一个条目 - 第一部分和最后一部分由系统调用 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 年,第 69-71 页。

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

请注意,amy 文件系统对象可以使用 mknod(2) 创建:常规文件、目录、设备文件、符号链接等。因此,为了回答OP的问题之一,是的,目录是一个文件,这意味着,“它是一个对象,由 inode 表示,驻留在通过 i/o 接口运行的文件系统中”。

答案3

如果你想了解更多有关 Unix/Linux 文件系统的信息,我推荐你两本书了解 Linux 内核Linux 内核开发。这些是了解 Linux 内核的最佳书籍。

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

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

答案4

你可以从阅读开始http://www.freebsd.org/doc/en/books/design-44bsd/book.html#OVERVIEW-FILESYSTEM。更多详情请参阅优秀经典书籍《4.4 BSD操作系统的设计与实现》。

相关内容