温馨提示×

linux readdir会阻塞吗

小樊
35
2026-09-20 22:45:29
栏目: 智能运维

简短结论:readdir() 本身在“正常本地文件系统”下一般不会阻塞(除了极短时间的内部锁/互斥),但它并不是绝对非阻塞的,是否阻塞取决于底层文件系统、挂载方式和具体实现。

下面分情况说清楚。


1. 普通本地文件系统(ext4 / xfs / btrfs 等)

  • readdir()(以及 readdir_r())通常不会长时间阻塞
  • 它只是从内核已经缓存或逐步返回的目录项中读取下一项
  • 大部分情况下:
    • 第一次 opendir() 可能触发少量 I/O
    • 后续 readdir() 一般是内存操作

✅ 一般不会阻塞


2. 网络文件系统(NFS / CIFS / SMB / SSHFS)

可能会阻塞,甚至可能阻塞很久

例如:

  • NFS 服务端无响应
  • 网络延迟高
  • 服务端挂死

此时:

  • readdir() 可能卡在:
    • 网络 RTT
    • 服务端超时
    • 内核重试逻辑

⚠️ 可能长时间阻塞(秒级到分钟级)


3. 特殊 / 虚拟文件系统

可能阻塞的例子

  • /proc/
  • /sys/
  • FUSE 文件系统

如果:

  • FUSE daemon 卡住
  • 内核接口实现同步等待

那么 readdir() 会阻塞


4. readdir 和 getdents 的关系

  • readdir() 是 libc 封装
  • 内部调用 getdents64() 系统调用
  • 真正可能阻塞的是 系统调用层

所以:

阻塞的不是 readdir() 这个函数本身,而是底层 FS 的实现


5. 如何避免阻塞?

方案 1:使用非阻塞 I/O(有限)

  • readdir() 没有非阻塞版本
  • 但可以用:
    • openat() + O_NONBLOCK(对目录作用有限)

方案 2:放到线程里(最常见)

// 在 worker 线程中调用 readdir

方案 3:使用 io_uring(Linux 5.1+)

  • 支持异步 readdir
  • 真正非阻塞目录遍历(需较新内核)

方案 4:避免遍历“危险目录”

  • 不遍历 /net、/mnt/*、FUSE 挂载点
  • 设置超时机制

6. 一句话总结

readdir() 在本地磁盘上基本不阻塞,但在网络/虚拟/异常文件系统中可能严重阻塞。

如果你愿意,我可以:

  • 给你一个 非阻塞目录遍历示例
  • 或分析你具体用的 文件系统 / 场景(NFS?docker?FUSE?)

0 踩