温馨提示×

linux readdir为何卡住不动

小樊
35
2026-09-23 23:13:09
栏目: 智能运维

readdir 在 Linux 下“卡住不动”通常不是函数本身的问题,而是底层文件系统或目录状态导致它阻塞了。下面按常见原因逐一说明,并给出排查思路。


一、最常见原因

1. 目录在「网络文件系统」上(NFS / CIFS / FUSE)

如果目录在:

  • NFS
  • SMB/CIFS
  • sshfs
  • 其他 FUSE 文件系统

而服务端无响应,那么:

readdir()

会一直阻塞,表现为“卡住”。

✅ 排查:

mount | grep <目录>

或

df -h <目录>

✅ 验证是否网络问题:

ls <目录>     # 同样会卡

2. 目录本身非常大(百万级文件)

readdir 本身是流式的,但:

  • 第一次 opendir + 第一次 readdir
  • 或某些文件系统(如 ext4 大目录)

需要读取大量 inode,可能看起来卡住几秒到几分钟。

✅ 特征:

  • CPU 不高
  • 磁盘 IO 很高

✅ 排查:

ls -l | wc -l

3. 目录是一个「挂载点卡死」

例如:

  • 自动挂载(autofs)
  • 未响应的 USB / 移动硬盘
  • 失效的 loop 设备

readdir 会阻塞在 VFS 层。

✅ 检查:

mount
dmesg | tail

4. 目录是一个「特殊文件 / 设备文件」

例如误用:

opendir("/dev")
readdir(...)

某些设备节点会导致阻塞(罕见但存在)。

✅ 建议:

  • 不要对 /proc、/sys、/dev 随意 readdir

5. 程序被「D 状态」卡住(不可中断睡眠)

readdir 在等内核 IO,进程处于:

D (uninterruptible sleep)

✅ 查看:

ps -eo pid,stat,cmd | grep your_proc

✅ 特征:

  • kill -9 也杀不掉
  • 只能等 IO 恢复或重启

二、代码层面的可能问题

1. 忘记检查返回值

while ((ent = readdir(dir)) != NULL)

如果 readdir 返回 NULL 且 errno 被设置,你可能误以为是“卡住”。

✅ 正确写法:

errno = 0;
while ((ent = readdir(dir)) != NULL) {
    ...
}
if (errno != 0) {
    perror("readdir");
}

2. 多线程中目录被并发修改

  • 另一线程 rm -rf
  • 或 NFS 目录频繁变化

可能导致 readdir 反复重试。


三、如何快速定位“卡在哪”

1. strace

strace -p <pid>

你会看到类似:

readdir(3,

一直不动 → 内核层阻塞


2. cat /proc/<pid>/stack

cat /proc/<pid>/stack

能看到内核调用栈(需要 root)。


四、总结一句话

readdir 卡住,99% 不是 readdir 的锅,而是它背后的文件系统“动不了”。

如果你愿意,可以补充:

  • 目录路径(本地 / NFS / docker / 容器)
  • 是否多线程
  • strace 输出
  • 文件系统类型

我可以更精确地帮你定位。

0 踩