在 Debian / Linux 下,readdir 的实现涉及 用户态 glibc 和 内核 VFS 两层。下面按“从你调用 readdir() 到内核返回目录项”的完整流程说明。
readdir() 是什么在 Debian 中,readdir() 是 POSIX 标准接口,定义在:
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
它用于读取一个打开目录流中的下一个目录项。
readdir() 实现(用户态)Debian 使用 glibc,其 readdir() 实现大致流程如下:
opendir() 打开目录DIR *dir = opendir("/tmp");
opendir() 内部会:
open(dirpath, O_RDONLY | O_DIRECTORY)DIR * 结构体(包含 fd、缓冲区等)readdir() 内部逻辑glibc 的 readdir() 不是直接对应一个系统调用,而是封装了 getdents / getdents64。
简化逻辑如下:
struct dirent *readdir(DIR *dirp)
{
if (dirp->buf_pos >= dirp->buf_end) {
// 从内核读取一批目录项
int n = syscall(SYS_getdents64, dirp->fd,
dirp->buf, sizeof(dirp->buf));
if (n <= 0)
return NULL;
dirp->buf_pos = 0;
dirp->buf_end = n;
}
// 从缓冲区解析一个 dirent
struct dirent *entry = (struct dirent *)(dirp->buf + dirp->buf_pos);
dirp->buf_pos += entry->d_reclen;
return entry;
}
✅ 关键点:
readdir() 是 缓冲式读取struct direntgetdents / getdents64| 函数 | 说明 |
|---|---|
getdents |
老接口(32 位) |
getdents64 |
新接口(64 位 inode) |
glibc 在 Debian amd64 上通常使用 getdents64。
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
struct linux_dirent64 __user *, dirp,
unsigned int, count)
路径:
getdents64
└── vfs_readdir()
└── file->f_op->iterate_shared()
└── 具体文件系统
int vfs_readdir(struct file *file, struct dir_context *ctx)
VFS 统一目录读取接口。
以 ext4 为例:
ext4_dir_operations = {
.iterate_shared = ext4_readdir,
};
ext4_readdir() 会:
struct direntstruct direntstruct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct linux_dirent64struct linux_dirent64 {
u64 d_ino;
s64 d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
#include <stdio.h>
#include <dirent.h>
int main() {
DIR *dir = opendir(".");
if (!dir) return 1;
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
return 0;
}
编译:
gcc readdir.c -o readdir
Debian 中的
readdir()是 glibc 对getdents64系统调用的封装;内核通过 VFS 调用具体文件系统(如 ext4)读取目录数据并返回目录项。
如果你愿意,我可以:
readdir vs getdents vs readdir_r你更想深入哪一块?