温馨提示×

linux readdir如何工作

小樊
40
2026-10-26 04:23:54
栏目: 智能运维

在 Linux 中,readdir 是用于读取目录内容的一组函数和机制,常见于 C 语言编程。理解它需要从系统调用、库函数、底层文件系统三个层面来看。


一、readdir 是什么

readdir 是 POSIX 标准 定义的目录读取函数,用于在用户空间遍历目录中的文件和子目录。

常见相关函数:

#include <dirent.h>

DIR *opendir(const char *path);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);

二、readdir 的基本使用流程

DIR *dir = opendir("/tmp");
struct dirent *entry;

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

closedir(dir);
  • opendir:打开目录,返回一个 DIR*
  • readdir:每次返回一个目录项
  • closedir:关闭目录

三、readdir 在 Linux 中的工作原理

1️⃣ 用户态层面(glibc)

readdir 是 glibc 封装的函数,不是直接系统调用。

内部流程:

  1. opendir → 调用 open() 打开目录文件
  2. readdir → 从内核读取目录项并缓冲
  3. 返回 struct dirent

目录在 Linux 中也被视为文件,但内容是一系列目录项。


2️⃣ 内核态层面(系统调用)

真正的目录读取由以下系统调用完成:

getdents() / getdents64()
  • getdents64 是现代 Linux 使用的主要接口
  • 一次读取多个目录项到用户缓冲区
  • readdir 在内部维护缓冲区,逐条返回

调用关系:

readdir (glibc)
   ↓
getdents64 (syscall)
   ↓
文件系统驱动 (ext4 / xfs / overlayfs ...)

3️⃣ 文件系统的实现

不同文件系统实现不同,但逻辑类似:

  • 目录是一个特殊文件
  • 内部存储“文件名 → inode”的映射
  • 文件系统按索引或哈希顺序返回目录项

例如:

  • ext4:使用 HTree 或线性目录块
  • XFS:B+树
  • tmpfs:内存结构

四、struct dirent 结构

struct dirent {
    ino_t          d_ino;     // inode 号
    off_t          d_off;     // 偏移
    unsigned short d_reclen;  // 记录长度
    unsigned char  d_type;    // 文件类型
    char           d_name[];  // 文件名
};

⚠️ 注意:

  • readdir 不保证顺序
  • . 和 .. 也会返回
  • 并发修改目录可能导致漏读或重复

五、readdir 与 readdir_r 的区别

函数 特点
readdir 非线程安全(使用静态缓冲)
readdir_r 线程安全(已不推荐)
readdir64 支持大 inode

现代建议:

多线程中用 opendir + readdir 分别持有 DIR*


六、readdir 的性能特点

  • 一次 getdents64 可能读取几十~几百个目录项
  • 大目录(百万文件)可能较慢
  • 不适合频繁 stat 每个文件(用 getdents + statx 批量优化)

七、底层查看方式

查看系统调用:

strace ls /tmp

你通常会看到:

openat(AT_FDCWD, "/tmp", O_RDONLY|O_DIRECTORY)
getdents64(3, ...)

八、总结一句话

readdir 是 glibc 对 Linux getdents64 系统调用的封装,用于从文件系统中按块读取目录项,并以 struct dirent 的形式逐条返回给用户程序。

如果你愿意,我也可以:

  • 画一张调用流程图
  • 写一个简单的 getdents64 示例
  • 对比 readdir vs scandir vs fts

0 踩