温馨提示×

centos readdir啥时阻塞

小樊
44
2026-09-21 10:28:50
栏目: 智能运维

CentOS(及其他 Linux 发行版) 里,readdir() / readdir_r() 本身是 POSIX 标准函数,其底层依赖内核的 getdents() / getdents64() 系统调用。是否“阻塞”取决于 文件系统的实现和当前状态,而不是 CentOS 本身。

下面按常见情况说明 readdir 什么时候会阻塞


一、正常情况下:不阻塞(或几乎不阻塞)

  • 目录在 本地磁盘(ext4 / xfs)
  • 目录条目已被缓存(page cache / dcache)
  • 目录不大

此时 readdir 只是从内核缓存里取数据,非常快,不阻塞


二、会阻塞的典型场景

1️⃣ 首次读取大目录

  • 目录包含 几十万 / 上百万文件
  • 第一次 readdir
  • 内核需要:
    • 从磁盘读取目录项
    • 构建 dentry / inode 缓存

会阻塞,可能持续几百 ms 到数秒

CentOS 7/8 上大目录 readdir 慢是常见问题


2️⃣ 网络文件系统(NFS / CIFS / Gluster / CephFS)

这是 最常见的阻塞来源

NFS

  • readdir 需要向 NFS Server 发请求
  • 网络延迟、Server 负载高 → 阻塞
  • 大目录 + readdirplus → 更慢

CIFS / SMB

  • 每次 readdir 可能触发网络往返
  • 域控慢、网络丢包 → 明显卡住

readdir 可能阻塞数秒甚至更久


3️⃣ 目录对应的 inode 被锁住

以下情况会导致 readdir 阻塞:

  • 另一个进程正在:
    • rename()
    • unlink()
    • mkdir()
  • 文件系统正在:
    • fsync
    • 配额检查
    • 锁恢复(NFS)

✅ 短时间在 inode->i_rwsem 上等待


4️⃣ 文件系统本身“卡住”

例如:

  • NFS server 挂了(hard mount)
  • iSCSI / FC 存储断链
  • 分布式存储元数据节点异常

此时:

  • readdir 可能永久阻塞
  • ps 会看到 D 状态(不可中断睡眠)
ps -eo pid,stat,comm | grep D

5️⃣ FUSE 文件系统

  • 用户态文件系统(如:
    • sshfs
    • davfs
    • 自研 FUSE)
  • readdir 实际是调用用户程序

✅ 用户态逻辑慢 → readdir 阻塞


三、不会阻塞的情况

  • opendir() 已打开
  • 目录内容在 cache 中
  • 使用 readdir 循环遍历(非一次性)

四、如何确认 readdir 是否阻塞?

1️⃣ 查看进程状态

cat /proc/<pid>/stack

若看到:

getdents
iterate_dir

说明卡在 readdir

2️⃣ strace

strace -p <pid>

看到:

getdents64(...) = 0

且长时间不返回 → 阻塞


五、优化 / 规避建议

  • 避免超大目录(按时间 / hash 分目录)
  • NFS 使用 lookupcache=positive
  • 避免在网络文件系统上频繁 readdir
  • 使用 getdents64 + 批量读取
  • 必要时用线程隔离 readdir

如果你愿意,可以告诉我:

  • CentOS 版本
  • 文件系统类型(ext4 / xfs / nfs)
  • 目录大小

我可以给你 更具体的分析和解决方案

0