Linux Dentry(目录项)详解

什么是 Dentry?

Dentry(Directory Entry,目录项)是 Linux 文件系统中文件名与 inode 之间的映射关系。它本质上是一个数据结构,将人类可读的文件名转换为内核可识别的 inode 编号。

把文件系统想象成一个图书馆:dentry = 图书索引卡(书名 → 书架编号)inode = 书架编号对应的书架信息

Dentry 存了什么

字段含义
d_name文件名(如 test.txt
d_parent父目录的 dentry 指针
d_inode指向关联 inode 的指针
d_opdentry 操作函数集
d_sb所在文件系统的超级块

Dentry 没存什么

  • 文件内容 — 那是数据块的事
  • 文件元信息(权限/大小/时间戳) — 那些在 inode
  • inode 编号本身 — 它存的是指向 inode 结构体的指针

Dentry 的关键设计:解耦

dentry 的存在实现了 三层解耦

用户看到:  文件名          (dentry 管理)
                ↓
内核管理:  inode 编号      (inode 管理)
                ↓
实际存储:  数据块          (block 管理)

这种分离带来了两大能力:

1. 硬链接:两个 dentry 指向同一个 inode

ln file_a.txt file_b.txt
dentry "file_a.txt" ──┐
                       ├──→ inode #100 ──→ 数据块
dentry "file_b.txt" ──┘

两个文件名(两个 dentry)→ 同一个 inode → 同一份数据。这就是 link count = 2 的底层原理。

2. 删除与句柄分离:删除 dentry 不影响已打开的 fd

rm file.log  # 移除 dentry(目录项消失)
# 但进程还在读写 → inode 保留 → 空间不释放

进程持有已删除文件句柄 问题的本质正是:dentry 已删除,但 inode 引用未归零

dcache:缓存 dentry 加速路径解析

Linux 内核维护了一个 dcache(Directory Entry Cache,目录项缓存),用于缓存最近访问的 dentry。

为什么需要 dcache?

当你执行 cat /usr/share/doc/test.txt 时,内核需要逐级解析路径:

/               → 查找根目录的 dentry(已在 dcache)
usr             → 查找 / 下 usr 的 dentry
share           → 查找 usr 下 share 的 dentry
doc             → 查找 share 下 doc 的 dentry
test.txt        → 查找 doc 下 test.txt 的 dentry → 找到 inode

如果没有 dcache,每次访问文件都要从磁盘读取目录内容,性能极差。dcache 将解析结果缓存在内存中,下次访问同一路径直接命中。

查看 dcache

# 查看 dentry 缓存统计
slabtop -o | grep dentry
 
# 或
cat /proc/slabinfo | grep dentry

Dentry 的生命周期

创建文件(open / creat)
  → 在目录中添加 dentry(文件名 → inode 映射)
  → dentry 加入 dcache
  → link count + 1

读取文件
  → dcache 查找 dentry
  → 命中:直接获取 inode
  → 未命中:从磁盘读取目录内容,构造 dentry 加入 dcache

删除文件(unlink / rm)
  → 从目录中移除 dentry
  → dcache 中标记为无效
  → link count - 1
  → 若 link count = 0 且无进程引用 → 回收 inode 和数据块

重命名文件(rename / mv)
  → 创建新 dentry(新文件名 → 原 inode)
  → 删除旧 dentry(旧文件名)
  → link count 不变

Dentry vs Inode vs fd 一图流

进程                      文件系统
┌──────┐   fd 3    ┌──────────┐   dentry   ┌───────┐  指针   ┌─────────┐
│ 应用  │ ────────→ │ 文件描述符 │ ────────→ │ dentry│ ──────→ │  inode  │ ──→ 数据块
└──────┘            │  表      │            │  "a.txt"│         │  #100  │
                    └──────────┘            └──────────┘         └──────────┘
                                              ↑
                                           目录文件
                                           (磁盘上的目录内容)
层次作用域创建/删除方式持久性
dentry内核 VFS 层open() / unlink()内存(dcache)+ 磁盘(目录内容)
inode文件系统层mkfs 时创建磁盘持久化
fd进程层open() / close()仅进程存活期间

相关笔记