刚刚开始阅读一些有关 Linux 文件系统的内容。我在好几个地方都找到了这样的引述:
Unix 目录是一系列关联结构,每个关联结构包含一个文件名和一个 inode 号。
所以我希望发现每个目录都包含其下文件的名称,每个文件映射到一个索引节点。但是当我vim directory_name
在 ubuntu 中这样做时,我得到这样的信息:
" ============================================================================
" Netrw Directory Listing (netrw v156)
" /Users/user/workspace/folder
" Sorted by name
" Sort sequence: [\/]$,\<core\%(\.\d\+\)\=\>,\.h$,\.c$,\.cpp$,\~\=\*$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
" Quick Help: <F1>:help -:go up dir D:delete R:rename s:sort-by x:special
" ==============================================================================
../
./
folder1/
folder2/
file1
file2
我希望在每个文件名旁边看到一个索引节点号,为什么不是这种情况?
答案1
这句话是关于 Unix 文件系统如何工作的(从逻辑上讲,现在的实际结构通常非常不同)。您可以使用以下-i
标志来查看索引节点号ls
:
$ ls -li
total 8
532028 -rw-r--r-- 1 anthony anthony 115 Apr 25 12:07 a
532540 -rw-r--r-- 1 anthony anthony 70 Apr 25 12:07 b
左边的数字就是索引节点。如果我运行ln b c
(创建硬链接),那么:
$ ls -li
total 12
532028 -rw-r--r-- 1 anthony anthony 115 Apr 25 12:07 a
532540 -rw-r--r-- 2 anthony anthony 70 Apr 25 12:07 b
532540 -rw-r--r-- 2 anthony anthony 70 Apr 25 12:07 c
权限和大小是 inode 的一部分,而不是目录的一部分。通过之后发生的事情很容易看出chmod 0600 c
:
$ ls -li
total 12
532028 -rw-r--r-- 1 anthony anthony 115 Apr 25 12:07 a
532540 -rw------- 2 anthony anthony 70 Apr 25 12:07 b
532540 -rw------- 2 anthony anthony 70 Apr 25 12:07 c
两者都b
发生c
了变化,因为它们共享相同的 inode。
但是,内核仅通过定义良好的 API 将文件系统公开给用户空间(除了原始设备,如/dev/sda1
)。它允许用户空间访问一堆系统调用,以执行创建和删除链接、更改权限、读写文件、重命名等操作。它不会向用户空间公开原始的底层文件系统数据结构。这是有很多充分的理由的:它允许网络文件系统,这意味着内核可以强制执行权限并保持文件系统数据结构的正确性,这意味着您可以使用不同的文件系统(具有不同的数据结构)而无需更改用户空间。
所以,基本上,vim dir
只是向您显示一个目录列表 - 或多或少就像这样ls
做。它是通过一个名为 Netrw 的 vim 模块完成的,正如它上面所说的那样(:help netrw
在 vim 中尝试)。您实际上无法编辑底层文件系统数据结构。
答案2
从语义上讲,目录是从文件名到 inode 的映射。这就是目录树抽象的设计方式,对应于应用程序和文件系统之间的接口。应用程序可以按名称指定文件并枚举目录中的文件列表,每个文件都有一个唯一的指示符,称为“inode”。
如何实现此语义取决于文件系统类型。目录的编码方式取决于每个文件系统。在大多数 Unix 文件系统中,目录是从文件名到 inode 编号的映射,并且有一个单独的表将 inode 编号映射到 inode 数据。 (inode数据包含文件元数据,例如权限和时间戳,文件内容的位置等)映射可以是列表,哈希表,树......
您无法使用 Vim 查看此映射。 Vim 不显示代表目录的存储区域。 Linux 与许多其他现代 Unix 系统一样,不允许应用程序直接查看目录表示形式。当涉及到目录条目和元数据时,目录的行为与普通文件类似,但涉及到其内容时则不然。应用程序通过open
、read
、write
、等系统调用从普通文件读取close
;对于目录,还有其他系统调用:opendir
、readdir
、closedir
和修改目录是通过创建、移动和删除文件来完成的。像这样的应用程序cat
使用open
, read
,close
来读取文件的内容;像这样的应用程序ls
使用opendir
, readdir
,closedir
来读取目录的内容。 Vim 通常的工作方式类似于cat
读取文件的内容,但如果您要求它打开一个目录,它的工作方式类似于ls
并以格式良好的方式打印数据。
如果您想查看目录的内部结构,可以使用debugfs
ext2/ext3/ext4 等工具。确保您没有修改任何内容!像这样的工具debugfs
可以绕过文件系统并彻底破坏它。 ext2/ext3/ext4debugfs
是安全的,因为它处于只读模式,除非您明确允许通过命令行选项进行写入。
# debugfs /dev/root
debugfs 1.42.12 (29-Aug-2014)
debugfs: dump / /tmp/root.bin
debugfs: quit
# od -t x1 /tmp/root.bin
/
您将在一堆其他字符中看到目录条目的名称,其中一些字符是不可打印的。为了理解它,您需要了解文件系统格式的详细信息。
答案3
我怀疑您可能正在阅读一本关于 Unix 文件系统如何工作的非常非常古老的阐述。您所描述的内容在 20 世纪 70 年代末左右是正确的,但在任何现代文件系统上都不再正确。
在许多现代平台上,有几种常用的文件系统,每个文件系统都向用户空间隐藏其内部结构。您可以了解它们的样子并使用它们,但是除非您想专门设计文件系统,否则最好相信本书的作者足以让您对设计有一个基本的了解,而无需深入了解太多的细节(无论如何,当你再次需要它时,其中一些细节将会过时)。