问题源于eventfd/timerfd/signalfd等内核匿名fd被lsof默认忽略,需通过lsof -e/-d选项、/proc/pid/fdinfo/type字段、inotifywait监控、bpftrace追踪系统调用或/proc/pid/status中fds与fdsize对比来定位。

当系统报错“too many open files”,但使用 lsof 查看进程打开文件数却显示极少,尤其未见大量 eventfd、timerfd 或 signalfd 等 fd 时,问题往往源于这些 fd 被内核隐藏——它们不被 lsof 默认识别或枚举。以下是定位与暴露这些隐藏 fd 的具体操作:
一、启用 lsof 的 -e 选项强制扫描所有 fd 类型
默认 lsof 会跳过部分匿名 fd(如 eventfd/timerfd),需显式启用扩展扫描模式以覆盖内核抽象 fd。
1、执行命令:lsof -p
2、若失败,改用:lsof -p
3、检查输出中是否出现 anon_inode 字样,该字符串即为 eventfd/timerfd/signalfd 的统一标识。
二、直接读取 /proc//fdinfo/ 下的 fd 元数据
/proc/
1、列出目标进程所有 fd 编号:ls -l /proc/
2、逐个检查 fdinfo:grep -H "type:" /proc/
3、统计匹配行数:grep -H "type:" /proc/
三、使用 inotifywait 捕获 fd 创建行为
若隐藏 fd 动态高频创建,可在进程启动前注入监控,实时捕获 anon_inode fd 的生成事件。
1、在目标进程工作目录运行:inotifywait -m -e create,attrib /proc/
2、触发业务逻辑使进程创建新 fd,观察 inotifywait 输出中新增的数字文件名。
3、立即对新文件执行:cat /proc/
四、通过 eBPF 工具 bpftrace 实时追踪 syscalls
利用内核级追踪绕过用户态工具限制,直接捕获进程调用 eventfd2()、timerfd_create()、signalfd4() 等系统调用的行为。
1、安装 bpftrace 后执行:bpftrace -e 'tracepoint:syscalls:sys_enter_eventfd2 { printf("eventfd created by PID %d\n", pid); }'。
2、并行运行:bpftrace -e 'tracepoint:syscalls:sys_enter_timerfd_create { printf("timerfd created by PID %d\n", pid); }'。
3、合并输出结果,筛选出目标 PID 对应的创建记录,确认其调用频次与 ulimit -n 限制的关系。
五、检查 /proc//status 中的 FDSize 与 FDs 字段
/proc/
1、执行:grep -E "FDSize|FDs" /proc/
2、若 FDs 值接近或等于 FDSize,且远高于 lsof 报告值,则说明大量 fd 属于内核匿名类型,未被 lsof 枚举。
3、对比:cat /proc/










