目录
[1. 引言](#1. 引言)
[2. 目录文件的结构](#2. 目录文件的结构)
[3. 路径解析](#3. 路径解析)
[4. 目录项缓存(dentry cache)](#4. 目录项缓存(dentry cache))
[5. 挂载(Mount)](#5. 挂载(Mount))
[5.1 什么是挂载?](#5.1 什么是挂载?)
[5.2 挂载实验(文档中的示例)](#5.2 挂载实验(文档中的示例))
[5.3 挂载点与路径解析](#5.3 挂载点与路径解析)
[6. 软链接与硬链接](#6. 软链接与硬链接)
[6.1 硬链接(Hard Link)](#6.1 硬链接(Hard Link))
[6.2 软链接(Symbolic Link)](#6.2 软链接(Symbolic Link))
[6.3 软硬链接对比](#6.3 软硬链接对比)
[6.4 文件备份与硬链接](#6.4 文件备份与硬链接)
[7. 文件的三个时间戳(补充)](#7. 文件的三个时间戳(补充))
[8. 小结](#8. 小结)
1. 引言
我们已经知道文件由inode和数据块组成,但用户通过路径名 (如/home/whb/test.c)访问文件,而不是inode号。本文揭示目录文件如何将文件名映射到inode,解释Linux路径解析的过程、挂载的实现,以及软硬链接的区别与用途。
2. 目录文件的结构
-
目录也是一种文件,有自己的inode和数据块。
-
目录的数据块中存储一系列目录项(directory entry),每个目录项包含:
-
文件名(变长)
-
对应的inode号
-
文件类型等
-
可以使用readdir系统调用来遍历目录内容,示例代码(见文档)可以打印出目录下每个文件的名字和inode号。
c
struct dirent {
ino_t d_ino; // inode号
off_t d_off; // 偏移
unsigned short d_reclen;
unsigned char d_type;
char d_name[256]; // 文件名
};
因此,要打开文件/home/whb/test.c,需要:
-
打开根目录
/,读取其数据块,找到home对应的inode号 -
打开
home目录,找到whb的inode -
打开
whb目录,找到test.c的inode -
最终根据inode读取文件内容
3. 路径解析
路径解析就是根据路径字符串,从根目录开始,逐级查找目录项,直到获得目标文件或目录的inode号。解析过程中,每一步都需要打开当前目录文件,读取其数据块,匹配下一个分量。
为什么路径解析效率不高?
每次查找目录项都可能涉及磁盘I/O。为了加速,Linux内核引入了目录项缓存(dentry cache)。
4. 目录项缓存(dentry cache)
-
struct dentry是内核中表示路径分量的结构体,构成一棵内存中的目录树。 -
已经解析过的路径会缓存在dentry cache中,再次访问时无需从磁盘重新读取。
-
Dentry还关联了对应的inode(已缓存在inode cache中),从而实现快速路径查找。
-
缓存使用LRU算法淘汰旧项。
好处: 极大提升文件系统性能,尤其是频繁访问的路径。
5. 挂载(Mount)
5.1 什么是挂载?
-
挂载是将一个文件系统(通常存储在一个分区上)关联到现有目录树中的某个目录(挂载点)的过程。
-
挂载后,访问该目录就相当于访问那个分区上的文件系统。
5.2 挂载实验(文档中的示例)
bash
# 创建虚拟磁盘文件并格式化为ext4
dd if=/dev/zero of=disk.img bs=1M count=5
mkfs.ext4 disk.img
# 创建挂载点目录
mkdir /mnt/mydisk
# 挂载
mount -t ext4 disk.img /mnt/mydisk
# 查看分区信息
df -h
# 卸载
umount /mnt/mydisk
/dev/loop0是循环设备,允许将普通文件模拟为块设备。
5.3 挂载点与路径解析
挂载点实际上是一个交叉点:内核在进行路径解析时,当进入一个挂载点目录,会自动切换到对应文件系统的根目录。因此,同一路径前缀可能跨越不同分区,但用户无感知。
6. 软链接与硬链接
6.1 硬链接(Hard Link)
-
硬链接是在目录文件中创建一个新的目录项,指向同一个inode。
-
创建硬链接:
ln source target -
硬链接的inode链接计数(
i_links_count)会增加。 -
删除文件时,链接计数减1,只有当计数为0时才真正释放inode和数据块。
-
硬链接不能跨文件系统(因为inode号只在单个分区内唯一),也不能链接目录(防止循环)。
示例:
bash
touch abc
ln abc def
ls -li abc def # inode号相同,链接数=2
6.2 软链接(Symbolic Link)
-
软链接是一个特殊的文件 ,其数据块中存储了目标文件的路径字符串(而不是inode号)。
-
创建软链接:
ln -s source target -
软链接有自己的inode(不同号),文件大小等于路径字符串长度。
-
可以跨文件系统,可以链接目录。
-
若目标文件被删除,软链接变成悬空链接(broken link)。
示例:
bash
ln -s abc abc.sym
ls -li abc abc.sym # inode号不同,abc.sym -> abc
6.3 软硬链接对比
| 特性 | 硬链接 | 软链接 |
|---|---|---|
| 本质 | 目录项,指向同一inode | 独立文件,存储目标路径 |
| inode | 相同 | 不同 |
| 跨文件系统 | 否 | 是 |
| 可链接目录 | 否(防止循环) | 是 |
| 目标删除后 | 仍然有效(链接数-1) | 变成断链 |
| 占用空间 | 仅增加目录项 | 额外占用一个inode和数据块 |
6.4 文件备份与硬链接
硬链接可以节省磁盘空间:同一文件的多个副本通过硬链接实现,而不是复制数据。但修改任一链接都会影响所有链接,因为共享数据块。
7. 文件的三个时间戳(补充)
-
Access Time (atime) :最后访问时间(如
cat、less)。 -
Modify Time (mtime) :文件内容最后修改时间(如
echo > file)。 -
Change Time (ctime) :文件属性(inode元数据)最后修改时间(如
chmod、chown、硬链接计数变化)。
注意:ctime不是创建时间,stat命令中Creation time在某些文件系统(如ext4)中才有,需要内核支持。
8. 小结
本文讲解了目录文件的结构、路径解析过程、挂载机制,以及软硬链接的区别和用途。结合前几篇的内容,我们已经完整覆盖了从磁盘物理结构到文件系统组织、再到用户访问路径的全过程。理解这些知识,对于Linux系统管理、文件恢复、性能调优都有重要帮助。