【Linux】目录、路径解析、挂载与软硬链接

目录

[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) :最后访问时间(如catless)。

  • Modify Time (mtime) :文件内容最后修改时间(如echo > file)。

  • Change Time (ctime) :文件属性(inode元数据)最后修改时间(如chmodchown、硬链接计数变化)。

注意:ctime不是创建时间,stat命令中Creation time在某些文件系统(如ext4)中才有,需要内核支持。

8. 小结

本文讲解了目录文件的结构、路径解析过程、挂载机制,以及软硬链接的区别和用途。结合前几篇的内容,我们已经完整覆盖了从磁盘物理结构到文件系统组织、再到用户访问路径的全过程。理解这些知识,对于Linux系统管理、文件恢复、性能调优都有重要帮助。