在 Linux 中,readdir 是用于读取目录内容的一组函数和机制,常见于 C 语言编程。理解它需要从系统调用、库函数、底层文件系统三个层面来看。
readdir 是 POSIX 标准 定义的目录读取函数,用于在用户空间遍历目录中的文件和子目录。
常见相关函数:
#include <dirent.h>
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);
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 是 glibc 封装的函数,不是直接系统调用。
内部流程:
opendir → 调用 open() 打开目录文件readdir → 从内核读取目录项并缓冲struct dirent目录在 Linux 中也被视为文件,但内容是一系列目录项。
真正的目录读取由以下系统调用完成:
getdents() / getdents64()
getdents64 是现代 Linux 使用的主要接口readdir 在内部维护缓冲区,逐条返回调用关系:
readdir (glibc)
↓
getdents64 (syscall)
↓
文件系统驱动 (ext4 / xfs / overlayfs ...)
不同文件系统实现不同,但逻辑类似:
例如:
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 |
线程安全(已不推荐) |
readdir64 |
支持大 inode |
现代建议:
多线程中用
opendir+readdir分别持有DIR*
getdents64 可能读取几十~几百个目录项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