温馨提示×

linux readdir为何卡住

小樊
49
2026-10-11 12:43:03
栏目: 智能运维

在 Linux 下 readdir()(或更常见的 opendir() + readdir())“卡住 / 阻塞”,通常不是函数本身有 bug,而是它正在等待某些系统资源或底层文件系统响应。下面按“最常见 → 较少见”的原因给你梳理。


一、最常见原因

1️⃣ 目录在网络文件系统上(NFS / SMB / FUSE)

这是 90% 的“readdir 卡住”原因。

  • NFS 服务端无响应
  • 网络丢包 / 延迟极高
  • 挂载使用了 hard 挂载(默认)
  • SMB(cifs)连接断开

表现:

opendir("/nfs/share");   // 可能卡
readdir(dir);            // 可能卡很久

✅ 验证:

mount | grep nfs
mount | grep cifs
df -h   # 是否卡住

✅ 解决:

  • 使用 soft,intr,timeo=10,retrans=2
  • 或 umount -l 懒卸载
  • 程序里加超时(用 alarm() / 多线程)

2️⃣ 目录下文件极多(百万级)

readdir() 本身不慢,但:

  • 内核需要读取大量 inode
  • 磁盘 IO 被打满

表现:

  • 第一次 readdir() 很慢
  • 看起来像“卡住”

✅ 验证:

ls -1 | wc -l

✅ 解决:

  • 避免超大目录
  • 使用数据库 / 分目录

3️⃣ 目录在慢速设备上

  • USB 硬盘
  • 机械盘高负载
  • 云盘(对象存储挂载)

✅ 检查:

iostat -x 1
dmesg | tail

二、系统 / 内核层面的原因

4️⃣ 文件系统损坏或 D 状态进程

如果进程状态是 D(不可中断睡眠):

ps -aux | grep your_proc

状态为 D+ → 等 IO,杀不掉。

✅ 原因:

  • 磁盘坏道
  • 存储控制器卡死

✅ 解决:

  • dmesg
  • 重启机器

5️⃣ FUSE 文件系统实现有问题

如果你是:

  • 自己写的 FUSE
  • 第三方 FUSE(rclone / sshfs)

readdir 会直接卡在用户态守护进程。

✅ 检查:

ps aux | grep fuse

三、程序层面的误解(不是真卡)

6️⃣ readdir 返回 NULL 但你在死循环

错误示例:

while ((entry = readdir(dir)) != NULL) {
    if (entry->d_name[0] == '.') continue;
}

看起来“卡住”,其实在扫大目录。


7️⃣ opendir 成功,但 readdir 被信号打断

  • EINTR 没处理
  • 多线程下锁竞争

四、如何快速定位问题

✅ 1. 看进程状态

top
# 看 STAT 是否为 D

✅ 2. 看调用栈

cat /proc/<pid>/stack

✅ 3. strace 看卡在哪

strace -p <pid>

如果卡在:

getdents64(...)

→ 文件系统问题


五、结论一句话

readdir 卡住 ≠ 函数问题,99% 是底层文件系统或 IO 阻塞

如果你愿意,可以把:

  • 卡住的目录路径
  • mount 输出
  • ps / strace 结果

发出来,我可以直接帮你定位是哪一种。

0 踩