news 2026/2/16 13:47:12

dentry 和 slab的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
dentry 和 slab的关系

目录标题

  • ✅ 概览(一句话版本)
  • 1) dentry 的内部(数据结构与生命周期 — 很重要)
      • struct dentry(关键字段与含义)
      • dentry 类型
      • 生命周期(核心)
  • 2) slab allocator(SLAB/SLUB/SLOB)与 dentry 的关系
  • 3) `/proc/slabinfo` 字段解析(如何精确计算内存占用)
  • 4) dentry 为什么会暴涨?常见根因(实战经验)
  • 5) 诊断/排查步骤与命令(从概览到定位进程)
      • 快速查看
      • 计算 dentry 内存(脚本)
      • 找出哪些目录 inode 很多 / 哪些目录文件多
      • 找出频繁 open/create 的进程(实时)
      • 找出谁在大量创建删除文件
      • 哪些进程持有大量 fd(可能是大量打开文件)
  • 6) 如何判断“是不是 dentry 导致的问题” — 指标与阈值(更精确)
  • 7) 线上缓解与根本解决(从轻到重、并说明副作用)
      • 临时缓解(会短暂影响性能)
      • 调整回收策略(推荐先试)
      • 文件系统/应用层面优化(根本)
      • FS 层面(如果是特定 FS)
  • 8) 防止复现的长期策略(监控+报警)
  • 9) 高级排查(内核级,必要时用)
  • 10) 常见误区纠正(避免踩坑)
  • 11) 常用脚本/命令汇总(可直接复制使用)
  • 12) 小结(如何把握优先级)
  • 1) 快速结论(先给结论省时间)
  • 2) 为什么会有这么高的 load(简要解释)
  • 3) 你现在可以立即做的诊断命令(按优先级,直接跑并把结果贴回我看)
  • 4) 根据你当前 slabtop / top 的发现,我的建议(实战)
  • 5) 我现在能帮你做的事(二选一或都可以)
  • 6) 补充 — 你可能关心的数据(我已从你输出总结)

✅ 概览(一句话版本)

  • dentry= VFS 的目录项缓存(每个路径组件一个 dentry),用于加速路径解析与复用目录元数据。
  • slab(slab/slub/slob)= 内核为小对象频繁分配提供的分配器。dentry 就是“被 slab 管理的一类对象”。
  • 过多的 dentry 会占用 slab(内核内存),影响可用内存并导致内核频繁回收,影响性能。

1) dentry 的内部(数据结构与生命周期 — 很重要)

(面向有内核/低层背景的读者,尽量贴近 linux 源码逻辑)

struct dentry(关键字段与含义)

  • d_name:目录项名(字符串 + length)
  • d_parent:指向父 dentry 的指针(形成树)
  • d_inode:关联的 inode 指针(NULL 表示 negative dentry)
  • d_count(引用计数):当前被多少地方持有(dget/dput 增减)
  • d_flags:状态位(例如 DCACHE_AUTOMOUNT 等)
  • d_lock(spinlock)/RCU 链表项:用于并发与哈希链
  • d_hash:hash table 中的哈希节点,用于快速查找同名 dentry
  • d_time/ LRU 链表:回收优先级用

dentry 类型

  • positive dentry:指向真实 inode 的 dentry(文件/目录存在)
  • negative dentry:表示某路径不存在(避免频繁 stat 查不到而打到 FS)

生命周期(核心)

  1. 路径解析(lookup)时:如果 hash 中无,创建 dentry(d_alloc) -> 可能立即填充 inode(d_splice_alias / inode->i_iget)。
  2. 使用时引用计数 ++(dget); 不使用时 dput(引用计数减为0时放入 LRU 回收队列)。
  3. 内核回收有两套机制:主动回收(shrinkers)+内存压力触发,还有vfs_cache_pressure控制 inode/dentry 的回收倾向。

2) slab allocator(SLAB/SLUB/SLOB)与 dentry 的关系

  • slab allocator 管理同类小对象(固定 objsize)的缓存池。每种对象类型(例如dentry)都会有自己的缓存(cache)。
  • slab 内部按 slab(页)分块,每页能放 N 个 obj。/proc/slabinfoslabtop就是从这里取统计数据。
  • 当 dentry 被创建,会从dentryslab cache 分配一块,释放时放回 slab cache(未必马上归还给页分配器)。

3)/proc/slabinfo字段解析(如何精确计算内存占用)

典型行(示例):

dentry 1538418 1588545 192 42 2 : tunables 0 0 0 : slabdata 37823 37823 0

字段按顺序(常见格式):

  • name
  • active_objs(活动对象数,当前仍被引用/在使用的)
  • num_objs(总对象数,包含 free 的)
  • objsize(每个对象的大小,bytes)
  • obj_per_slab(每 slab 能放多少对象)
  • pages_per_slab(每 slab 占用多少页)
  • : tunables ... : slabdata ...(更细的 runtime 数据,slab 数等)

常用计算方式(两种)

  • 近似法(简单)mem ≈ active_objs * objsize—— 快速估算活跃对象占用
  • 精确法(按 slab)num_slabs = slabdata_active(或用 num_objs / obj_per_slab 向上取整) →total_mem = num_slabs * pages_per_slab * PAGE_SIZE
    (PAGE_SIZE 通常 4096)

你之前的示例:1538418 * 192 ≈ 295,373,000 B ≈ 282 MB—— 就是用粗略法,足够判断级别。


4) dentry 为什么会暴涨?常见根因(实战经验)

  • 程序遍历大量目录(例如:递归扫描 /data、find /、备份脚本、误写的 for 循环)
  • 应用频繁创建/删除大量小文件(短生命周期文件)
  • 容器/Pod 日志文件无限增长或不停 rotate(产生大量 inode/dentry)
  • 监控/agent/安全软件频繁 stat/fstat/scan(例如 antivirus、文件完整性检测)
  • NFS/网络文件系统异常导致 negative dentry 增多(缓存的不存在路径)
  • bug:程序对文件系统做了“热”操作(如无限循环 open/close)

5) 诊断/排查步骤与命令(从概览到定位进程)

我按从“快排查”到“精查”的顺序给命令和脚本。遇到线上问题时按这个走能快速落点。

快速查看

# slab 总览cat/proc/slabinfo|egrep'dentry|inode|buffer_head|kmalloc'# slabtop 交互式(实时)slabtop -s c -o# 内存概览free-h;vmstat15;top-b -n1|head-20# page cache 大小grep-i'^Cached:'/proc/meminfogrep-i'^Active:'/proc/meminfo

计算 dentry 内存(脚本)

awk'/^dentry/ {printf "active=%d, num=%d, objsize=%d => approx_mem=%0.2fMB\n",$2,$3,$4,($2*$4)/1024/1024}'/proc/slabinfo

找出哪些目录 inode 很多 / 哪些目录文件多

# top dirs by # of inodes (目录级别统计)fordin/*;doecho"$(find"$d"-xdev -type f2>/dev/null|wc-l)$d";done|sort-n# 更深的按目录列 inode count(慢)find/ -xdev -printf'%h\n'2>/dev/null|sort|uniq-c|sort-nr|head

找出频繁 open/create 的进程(实时)

  • 推荐用bcc / eBPFopensnoop-bpfcc(需要 bcc 工具)
# 需要安装 bcc-toolsopensnoop-bpfcc -t5# 监控 5 秒内的 open
  • 或用sysdig/strace -f -p(重):
sysdig evt.type=open and fd.name contains /path# sysdig 筛选

找出谁在大量创建删除文件

  • 使用inotify/auditd/eBPF 工具来追踪unlink/open/creat系统调用:
# bpftrace 例子:统计每个 pid 的 open 系统调用计数sudobpftrace -e'tracepoint:syscalls:sys_enter_openat { @[comm]++; }'

哪些进程持有大量 fd(可能是大量打开文件)

lsof|awk'{print$1}'|sort|uniq-c|sort-nr|head# or per pidforpidin$(ls/proc|egrep'^[0-9]+$'|head);doecho-n"$pid";ls/proc/$pid/fd|wc-l;done|sort-k2 -n|tail

6) 如何判断“是不是 dentry 导致的问题” — 指标与阈值(更精确)

  • 观察/proc/slabinfodentryactive_objs * objsize占总内存比例。
  • 结合free:如果available很低,kswapd占 CPU 高且 slab 中 dentry 占显著比例 → dentry 可能是主要原因。
  • 经验阈值(实践):当 dentry 占用超过系统内存的 5–10%时值得警惕;超过20%则很可能影响系统(但具体看 workload)。
    (你机器 47G 下 280MB = 0.6%,完全安全 —— 你之前的结论正确)

7) 线上缓解与根本解决(从轻到重、并说明副作用)

临时缓解(会短暂影响性能)

# 清 page cacheecho1>/proc/sys/vm/drop_caches# 清 dentry+inodeecho2>/proc/sys/vm/drop_caches# 清 page+inode+dentryecho3>/proc/sys/vm/drop_caches

注意:这是无害的“缓存丢弃”操作,但会让系统重新热加载缓存,短期内可能降低性能。不能作为根本长期策略。

调整回收策略(推荐先试)

# 提高内核回收 dentry 的积极性(默认 100)sysctl -w vm.vfs_cache_pressure=200# 永久写入 /etc/sysctl.conf
  • vfs_cache_pressure越高,内核越倾向回收 dentry/inode(但可能增加 I/O,因为要频繁重新 stat/read)。

文件系统/应用层面优化(根本)

  • 减少频繁创建/删除短文件:使用一批预分配文件或内存队列/缓存。
  • 拆分大目录:避免单目录内大量文件(Hash 分桶)。
  • 日志轮转/压缩策略:合理设置 logrotate,限制容器日志;对容器日志启用 log rotation 或限速。
  • tmpfs:短期高频文件放 tmpfs(内存)减少磁盘 inode/dentry 压力,但要看内存预算。
  • mount optionsnoatime/nodiratime减少无谓写操作(对创建/读取压力帮助有限,但常见优化)。
  • 调整应用:避免在高并发场景中频繁statscandir

FS 层面(如果是特定 FS)

  • XFS/EXT4 有不同 inode/dentry 行为:例如对小文件很多的场景,用 XFS+合理 inode 配置可能更优。
  • 对已有磁盘,可考虑增加文件系统的 directory hash / readdir 性能 tuning。

8) 防止复现的长期策略(监控+报警)

  • 监控dentry大小(使用 prometheus node_exporter 的 slab 或者自写 exporter 抓/proc/slabinfo
  • 监控Cached/Buffers/Active/Available,结合kswapdCPU 占用报警
  • 监控文件系统中文件数(df -i)和单目录文件数量
  • 记录开、关机时的 baseline slabinfo,异常时对比

9) 高级排查(内核级,必要时用)

  • ftrace:trace d_alloc/dput 行为,找出哪个 task 调用频繁
  • kernel slab leak detection / kmemleak:如果怀疑内核对象泄露(不是普通的 cache 增大)
  • perf:查看系统在 file IO/kswapd/softirq 等处消耗
  • BPF 程序:写 tracepoints 统计lookup/open/unlink按 comm/pid/path 的热点

示例 bpftrace 统计 open 系统调用按进程:

sudobpftrace -e'tracepoint:syscalls:sys_enter_openat { @[comm] = count(); }'

10) 常见误区纠正(避免踩坑)

  • 误以为 dentry 是 page cache 的一部分:两者不同,dentry 属于 slab(对象缓存),page cache 属于页缓存;drop_caches有时会同时影响这两者。
  • 频繁 echo drop_caches 是好事:不是——会影响性能,掩盖根因。
  • “dentry 大 = 一定内存 leak”:不一定。很多场景是正常热缓存(例如大量小文件的服务),关键看是否造成内存压力与回收 thrash。

11) 常用脚本/命令汇总(可直接复制使用)

计算 dentry 占用百分比(更完整)

PAGE_SIZE=4096TOTAL_MEM_KB=$(awk'/MemTotal/ {print$2}'/proc/meminfo)# KBawk-vP=$PAGE_SIZE-vTM=$TOTAL_MEM_KB' /^dentry/ { active=$2; num=$3; objsize=$4; objs_per_slab=$5; pages_per_slab=$6; approx_active_mb = active * objsize / 1024 / 1024; # 更精确:用 num -> slab count -> pages * PAGE_SIZE slabs = int((num + objs_per_slab - 1) / objs_per_slab); precise_mb = slabs * pages_per_slab * P / 1024 / 1024; printf "dentry active_objs=%d objsize=%d -> approx_active=%.2fMB precise_total=% .2fMB (slabs=%d)\n", active, objsize, approx_active_mb, precise_mb, slabs; printf "dentry ~ %.3f%% of total mem\n", (approx_active_mb*1024)/(TM)/10.24; }'/proc/slabinfo

监测短时间内哪个进程在 open/create 文件

# opensnoop-bpfcc 需安装 bccsudoopensnoop-bpfcc -n10# top 10 files with open events

12) 小结(如何把握优先级)

  • 先看影响:是否有内存紧张、kswapd/oom 出现、IO/latency 增高?
  • 若无紧张:dentry 数高很可能只是缓存热身(不处理)。
  • 若有紧张:按上面诊断顺序(slabinfo -> top dirs by inode -> eBPF tracking -> fix app/fs)逐步定位并修复。
  • 长期防范:监控 + 限制容器日志与短生命周期文件写入 + 优化应用逻辑。

生产环境


1) 快速结论(先给结论省时间)

  • dentry 大小active=2,258,037 * objsize=216B ≈ 465.14 MB
    占总内存(502 GiB)的比例约0.09%——完全不算高 / 无需处理
  • 真正占用较多的是其它 slab & page cachebuffer_headxfs_inodekmalloc-512等占用了几 GB 到十几 GB
    slabtop 显示Active Size ≈ 10,144,671 KB (~9.67 GB);其中buffer_head单项约4,961,756 KB (~4.7 GB)xfs_inode2,152,480 KB (~2.05 GB)dentryslabtop 行列显示约643,280K?(你之前 slabtop 行列的 dentry 行显示 643,280K? 实际计算按 active*objsize 为 ~465MB)
  • 系统总体内存很空闲Mem total 502Giused 21Gibuff/cache 198Giavailable 477Gi—— 内存非常充足。
  • 异常点:系统load avg极高(~180),同时有大量kworkerxfs_ham+等在运行/D态并消耗大量系统 CPU(top 显示 system CPU ~44%),vmstat 显示磁盘 IO 活跃(bi/bo 很大)。这说明当前问题更可能是IO/文件系统(XFS)相关的高并发/元数据操作导致系统负载飙高,而不是 dentry 本身占内存。

结论:dentry 无需处理。应把精力放在找出导致高 load / 大量 I/O / 大量 kworker 的进程与操作(很可能与 XFS 元数据或 buffer_head 相关)并定位根因。


2) 为什么会有这么高的 load(简要解释)

  • load 很高但内存并不紧张,说明很多任务处于D(uninterruptible sleep)或等待 I/O,或大量内核线程在做 work(kworker、xfs 元数据处理等)。
  • slab 中buffer_head数量极大,表示 block layer 上有大量 buffers(通常和磁盘读写、元数据更新、XFS 缓冲有关)。
  • xfs_inode/xfs_ili数量大,说明 XFS 有大量 inode / I/O 元数据活动(可能是大量并发文件操作或后台扫描/repair/flush)。

3) 你现在可以立即做的诊断命令(按优先级,直接跑并把结果贴回我看)

  1. 实时查看 IO 负载与设备(快速定位是哪块盘):
iostat -x110
  1. 看哪个进程产生最多 I/O(需 iotop,若无先安装):
iotop -aoP# 或者 iotop -a -o -P
  1. 找出大量处于 D/正在做 IO 的进程(按 PID 列出状态):
ps-eo pid,stat,comm,%cpu,%mem --sort=-%cpu|head-n40# 或找 D 态进程ps-eo pid,stat,comm|awk'$2~ /D/ {print$0}'|head
  1. 查看内核日志是否有 XFS / I/O 错误:
dmesg|egrep-i'xfs|error|warn|i/o|hard io'|tail-n200journalctl -k -n200|egrep-i'xfs|i/o|error'
  1. 查看哪些目录文件数很多(可能导致元数据热点):
# top-level 快速统计fordin/*;doecho"$(find"$d"-maxdepth3-xdev -type f2>/dev/null|wc-l)$d";done|sort-nr|head# 若磁盘/目录明确,替换 /pathfind/path/to/suspected -xdev -printf'%h\n'|sort|uniq-c|sort-nr|head
  1. 追踪短时间内谁在 open/create(需要 bcc 或 bpftrace):
# opensnoop (bcc)sudoopensnoop-bpfcc -t10# bpftrace 快速统计 open 系统调用按 commsudobpftrace -e'tracepoint:syscalls:sys_enter_openat { @[comm] = count(); }'
  1. 查看每个进程打开的 fd 数(是否某进程打开数异常):
forpidin$(ls/proc|egrep'^[0-9]+$');doecho-n"$pid";ls/proc/$pid/fd2>/dev/null|wc-l;done|sort-k2 -n|tail-n30
  1. 如果怀疑 XFS 后台操作(scrub/repair/flush),列出 xfs 相关线程和命令行:
ps-ef|egrep-i'xfs|fsync|xfs_repair|xfs_io|xfs_fsr'|grep-vegrep

4) 根据你当前 slabtop / top 的发现,我的建议(实战)

  • 不要盲目 drop_caches(你内存大且缓存正常,drop 会引发短期性能降低并且掩盖根因)。
  • 把排查放在哪个进程 / 哪块磁盘 / 哪类操作上(opens/creat/unlink/fsync/stat),上述命令能迅速定位。
  • 若发现是某后台任务(比如备份、fsck、xfs_fsr、scrub、massive metadata scan)在跑,先考虑暂停/节流,观察 load 变化。
  • 如果是某应用在短时间内大量 create/unlink,建议:改为批量处理、减少 fsync、或者使用 tmpfs 缓冲再批量落盘。
  • 如果是 XFS 自身或内核 bug(dmesg 有错误或大量 xfs log 输出),请先把相关日志贴上来,我帮你分析是否需要升级内核或做特殊修复步骤。

5) 我现在能帮你做的事(二选一或都可以)

A. 你把下面输出贴来,我立即帮你分析并给出下一步建议(我会指出最可能的罪魁):

  • iostat -x 1 10的输出
  • iotop -aoP的前 50 行
  • dmesg | tail -n 200
  • ps -eo pid,stat,comm,%cpu --sort=-%cpu | head -n 60

B. 如果你愿意我也可以直接给一套“应急抑制”命令(例如对 suspect job 限速、nice/ionice 调整、临时停止某个服务),但我建议先定位再采取抑制,否则可能影响业务。


6) 补充 — 你可能关心的数据(我已从你输出总结)

  • dentry ≈465 MB(安全)
  • slab active 总体 ≈~9.7 GB(正常,主要是 buffer_head/xfs_inode/ kmalloc)
  • page cache (Cached:) ≈197,711,988 KB ≈ 188.5 GiB(这就是buff/cache很大的来源)
  • load 极高 + 大量 kworker/xfs 线程 →优先排 IO / XFS 元数据而不是 dentry

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/16 10:45:23

系统提示找不到msvcp140_codecvt_ids.dll文件 无法运行程序 下载修复

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/2/8 13:26:08

超细整理,性能测试如何做?怎么做?性能压力负载(汇总二)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 性能测试结果分析…

作者头像 李华
网站建设 2026/2/15 4:07:09

C++的第十四天笔记

存储持续性、作用域和链接性C使用三种(C11四种)不同方案存储数据。这些方案的区别在于数据保留在内存中的时间。自动存储持续性:在函数定义中声明的变量(包括函数参数),程序执行所属函数 / 代码块时创建&am…

作者头像 李华
网站建设 2026/2/3 10:44:47

874-LangChain框架Use-Cases - 基于智能体的动态槽位填充系统 - 案例分析

1. 案例目标 本案例旨在构建一个基于智能体的动态槽位填充系统,实现智能对话系统,能够分析用户请求并自动收集必要信息,通过对话补充缺失信息。 系统主要实现以下目标: 实现动态槽位填充功能,自动识别并收集必要信息…

作者头像 李华
网站建设 2026/2/5 3:01:14

ops-nn算子库生态纵览 - 构建健壮的AI算力基石

目录 🎯 摘要 1. ops-nn:CANN神经网络计算的中枢神经系统 1.1 🔄 算子库的定位与演进轨迹 1.2 📊 矩阵计算:AI算力的本质洞察 2. NPU硬件架构:算子设计的物理基础 2.1 🔧 AI Core微架构深…

作者头像 李华