温馨提示×

ubuntu readdir为何读取失败

小樊
37
2026-09-21 20:32:08
栏目: 智能运维

在 Ubuntu(Linux)下 readdir 读取失败,通常不是“系统 bug”,而是参数、权限、目录状态或使用方式出了问题。下面按最常见原因 → 排查方法 → 示例来说明。


一、readdir 是什么(先确认)

#include <dirent.h>

DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
  • readdir 返回 NULL 不代表一定失败
    • 读到目录末尾 → 返回 NULL,errno 不变
    • 真正出错 → 返回 NULL,且 errno 被设置

必须先检查 opendir 是否成功


二、最常见失败原因

1️⃣ 目录路径不存在或拼错

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

可能错误:

  • 路径不存在
  • 多写 / 或少写
  • 使用相对路径但工作目录不对

✅ 检查:

ls -ld /some/path

2️⃣ 权限不足(非常常见)

Permission denied

即使你是普通用户:

  • 父目录没有 x 权限
  • 目录本身没有 r 权限

✅ 检查:

ls -ld /path

✅ 解决:

chmod +rx /path

3️⃣ 目录被删除或卸载(TOCTOU 问题)

  • opendir 成功
  • 之后目录被删除 / 卸载 / 网络断开

此时:

readdir(dir); // 可能返回 NULL,errno = ENOENT

4️⃣ 传入了非法 DIR*

常见错误:

DIR *dir = NULL;
readdir(dir); // 未检查 opendir 返回值

或:

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

✅ 正确写法:

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

5️⃣ 网络/挂载目录问题(NFS、SSHFS、SMB)

  • 网络中断
  • 挂载点卡死

错误示例:

Input/output error
Stale file handle

✅ 检查:

mount | grep path
df -h

6️⃣ 同时修改目录(并发问题)

  • 另一个进程在删除/重命名文件
  • readdir 可能返回错误

一般不会致命,但可能:

  • 跳项
  • 返回 NULL + errno

三、如何判断“是真的失败”还是“读完了”

errno = 0;
struct dirent *entry = readdir(dir);
if (!entry) {
    if (errno != 0) {
        perror("readdir failed");
    } else {
        printf("end of directory\n");
    }
}

四、最小正确示例

#include <dirent.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char *argv[]) {
    if (argc < 2) return 1;

    DIR *dir = opendir(argv[1]);
    if (!dir) {
        perror("opendir");
        return 1;
    }

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

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

    closedir(dir);
    return 0;
}

五、调试建议(非常实用)

strace ./your_program /path

可以看到:

  • openat
  • getdents
  • 具体错误码

六、如果你愿意,我可以进一步帮你

你可以直接贴:

  1. 代码片段
  2. 错误输出(perror / errno)
  3. 目录类型(本地 / NFS / 挂载)

我可以精确告诉你 是哪一种失败原因

0