温馨提示×

ubuntu readdir会漏读文件吗

小樊
45
2026-10-03 16:10:53
栏目: 智能运维

简短结论:正常情况下 readdir 不会“漏读”文件,但在某些特殊场景下,确实可能出现“看起来像漏读”的现象。

下面分情况说明。


一、正常情况下:不会漏读

在 目录内容在遍历期间不发生变化 的情况下:

  • opendir + readdir + closedir
  • 内核会保证返回目录中所有条目(不重复、不遗漏)

例如:

DIR *dir = opendir(path);
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
    printf("%s\n", entry->d_name);
}
closedir(dir);

这是标准用法,不会漏文件。


二、可能导致“看起来漏读”的情况

1️⃣ 遍历过程中目录被并发修改(最常见原因)

如果在 readdir 遍历目录时:

  • 有进程在 创建 / 删除 / 重命名文件
  • 特别是在 大量文件高频变动 的场景

可能出现:

  • 某些文件未被读到
  • 某些文件被读到两次
  • 遍历提前结束或行为异常

原因:

  • 目录底层是 非线性结构(ext4 / xfs 等都是 B-tree 或 hash)
  • readdir 依赖 目录偏移量(inode 内部 cursor)
  • 并发修改会破坏遍历一致性

✅ 这是设计行为,不是 bug


2️⃣ 使用了 readdir_r 但 buffer 不正确(历史问题)

老代码常见错误:

struct dirent ent;
readdir_r(dir, &ent, &result); // 错误

正确应是:

struct dirent *ent = malloc(sizeof(struct dirent) + NAME_MAX + 1);

否则可能导致:

  • 读取异常
  • 程序崩溃
  • 看似“漏文件”

⚠️ 现代 glibc 已 废弃 readdir_r,建议只用 readdir


3️⃣ 文件数量极大(百万级)时的“假象”

  • readdir 本身不会漏
  • 但:
    • 程序逻辑错误(如提前 break)
    • 信号处理中断(EINTR)
    • 内存/性能问题导致逻辑跳过

常见误区:

“我刚创建的文件没列出来” 实际是:

  • 创建发生在 opendir 之后
  • 或落盘延迟(如 overlayfs / nfs)

4️⃣ 网络文件系统(NFS / CIFS / overlay)

在以下文件系统上:

  • NFS
  • SMB
  • Docker overlayfs
  • FUSE

readdir 一致性 弱于本地 ext4/xfs

可能出现:

  • 短暂漏读
  • 重复读
  • 顺序混乱

5️⃣ 隐藏文件 / 特殊文件误解

readdir 会返回:

  • .
  • ..
  • 隐藏文件(.file)

如果你“觉得漏了”,可能是:

  • 你手动过滤了
  • 没注意 . / ..

三、如何避免“漏读”问题

✅ 推荐做法:

  1. 遍历期间不要修改目录
  2. 若必须并发:
    • 先 ls / stat 一次快照
    • 或用 inotify 监听变化
  3. 本地文件系统优先
  4. 超大目录:
    • 分批处理
    • 或改用数据库 / 索引
  5. 不要依赖遍历顺序

四、一句话总结

readdir 本身不会漏读文件,但在目录并发修改、网络文件系统或错误使用 API 的情况下,会出现“漏读”的表象。

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

  • 你用的是 C / C++ / Python / shell
  • 是 本地还是 NFS
  • 文件量大概多少

我可以给你更具体的建议或示例代码。

0 踩