温馨提示×

linux readdir读取失败原因

小樊
39
2026-09-20 22:30:32
栏目: 智能运维

在 Linux 下使用 readdir()(或 readdir_r())读取目录时,“读取失败”通常表现为:

  • readdir() 返回 NULL
  • errno 被设置为某个错误码
  • 程序异常退出或读不到文件

下面按常见原因 → 说明 → 排查方法来总结。


一、目录未成功打开(最常见)

1. opendir() 失败

readdir() 必须在 opendir() 成功后使用。

DIR *dir = opendir(path);
if (!dir) {
    perror("opendir");
}

常见错误:

  • 路径不存在:ENOENT
  • 权限不足:EACCES
  • 不是目录:ENOTDIR

✅ 排查:

ls -ld /path

二、目录本身不可读 / 无权限

即使 opendir() 成功,目录也需要读权限(r):

chmod +r /path

错误码:

  • EACCES

✅ 检查:

namei -l /path

三、目录正在被修改(并发问题)

在以下情况 readdir() 可能行为异常:

  • 目录中文件被删除 / 新增
  • 另一个进程在写目录

虽然不一定“失败”,但可能:

  • 漏读
  • 重复读
  • 返回 NULL

✅ 建议:

  • 避免边读边写
  • 或先 scandir() 拷贝一份

四、目录项过多 / 大目录

对 超大目录(几十万+ 文件):

  • readdir() 本身不会失败
  • 但系统资源紧张时可能出问题

错误码:

  • EMFILE(文件描述符耗尽)
  • ENOMEM

✅ 排查:

ulimit -n

五、文件系统问题

1. 网络文件系统(NFS / SMB)

  • 网络中断
  • 挂载失败

错误码:

  • EIO
  • ESTALE(文件句柄失效)

✅ 检查:

mount | grep path
dmesg | tail

2. 磁盘损坏 / 只读

  • EIO
  • EROFS

六、错误地混用目录流

错误用法示例:

closedir(dir);
readdir(dir);   // ❌ 已关闭

或:

  • 多线程共用一个 DIR*
  • 未加锁

✅ 正确做法:

  • 一个线程一个 DIR*
  • 或使用 readdir_r()

七、符号链接问题

如果:

opendir("symlink")

而符号链接指向不存在目录:

  • ENOENT

✅ 检查:

readlink -f path

八、readdir 返回 NULL 不一定是失败

⚠️ 重要:

struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
    ...
}
  • 返回 NULL 可能只是读到结尾
  • 判断是否失败要看 errno

✅ 正确写法:

errno = 0;
entry = readdir(dir);
if (!entry && errno != 0) {
    perror("readdir");
}

九、32 / 64 位或 glibc 问题(较少见)

  • 旧系统使用 readdir() vs readdir64()
  • 大 inode 文件系统

✅ 建议:

  • 使用 readdir() + _FILE_OFFSET_BITS=64

十、常见错误码速查

errno 含义
ENOENT 目录不存在
EACCES 权限不足
ENOTDIR 不是目录
EBADF DIR 指针无效
EIO I/O 错误
EMFILE 文件描述符满
ESTALE 文件句柄失效

推荐调试模板

DIR *dir = opendir(path);
if (!dir) {
    perror("opendir");
    return;
}

errno = 0;
struct dirent *de;
while ((de = readdir(dir)) != NULL) {
    printf("%s\n", de->d_name);
}
if (errno != 0) {
    perror("readdir");
}
closedir(dir);

如果你愿意,可以:

  • 贴出 具体代码
  • 或 errno 值
  • 或 文件系统类型(ext4 / NFS)

我可以帮你精准定位原因。

0 踩