温馨提示×

linux readdir为何读取失败

小樊
37
2026-09-23 23:02:07
栏目: 智能运维

在 Linux 下使用 readdir(或 readdir_r)读取目录“失败”,通常不是函数本身有 bug,而是使用方式或环境不符合预期。下面按常见原因系统地说明。


一、最常见原因:没有先 opendir

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

struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
    ...
}

❌ 错误示例:

readdir(NULL); // 必然失败

✅ 检查:

  • opendir 返回值是否为 NULL
  • errno 是什么(EACCES、ENOENT 等)

二、目录路径不存在或权限不足

1. 路径错误

opendir("/tmp/nonexist_dir");

2. 权限不足

ls -ld /root

如果是:

drwx------ root root

普通用户无法 opendir

✅ 查看错误:

perror("opendir");

三、readdir 返回 NULL 不一定是“失败”

这是最容易误解的点。

while ((entry = readdir(dir)) != NULL) {
    ...
}
  • readdir 返回 NULL:
    • ✅ 目录读取结束(正常)
    • ❌ 发生错误(需检查 errno)

正确判断方式

errno = 0;
entry = readdir(dir);
if (entry == NULL) {
    if (errno != 0) {
        perror("readdir");
    } else {
        // 正常结束
    }
}

四、在多线程环境中用了 readdir

readdir 不是线程安全函数

❌ 错误:

// 多个线程同时调用 readdir(dir)

✅ 正确方案:

  • 使用 readdir_r(已不推荐)
  • 或加锁
  • 或使用 openat + getdents

五、目录被删除或卸载(TOCTOU 问题)

例如:

opendir("/mnt/usb");
// 此时 U 盘被拔掉
readdir(dir); // 失败

常见错误:

errno = ENOENT

六、符号链接导致的问题

opendir("link_to_dir");
  • 如果链接失效 → ENOENT
  • 如果指向无权限目录 → EACCES

✅ 可先 stat 或 realpath


七、文件系统不支持目录读取

某些特殊文件系统:

  • proc
  • sysfs
  • 网络挂载异常(NFS)

可能出现:

  • EIO
  • ENOTDIR

八、示例代码(推荐写法)

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

int main() {
    DIR *dir = opendir("/tmp");
    if (!dir) {
        perror("opendir");
        return 1;
    }

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

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

    closedir(dir);
    return 0;
}

九、如何快速定位你的问题

你可以补充:

  1. 错误现象(NULL?errno?)
  2. 使用的目录路径
  3. 是否是多线程
  4. 是否用 C / C++

我可以直接帮你定位代码问题。

0 踩