在 Linux 下使用 readdir(或 readdir_r / getdents)遍历目录时,性能瓶颈通常来自系统调用次数、内存分配、文件数量、文件元数据访问等。下面从「原理 → 常见优化手段 → 示例代码」系统讲一下。
readdir 底层依赖:
getdents / getdents64 系统调用问题点:
stat 每个文件会再次系统调用(非常慢)readdir 而不是 opendir + stat 混合如果你只需要文件名:
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
// 不要在这里 stat
}
❌ 错误示例(慢):
while (readdir(dir)) {
stat(entry->d_name, &st); // 每个文件一次系统调用
}
getdents64 自己控制缓冲(高性能)readdir 是封装,直接用 getdents64 可以:
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
char buf[1024 * 1024];
int fd = open(path, O_RDONLY | O_DIRECTORY);
while (1) {
int n = syscall(SYS_getdents64, fd, buf, sizeof(buf));
if (n <= 0) break;
// 解析 buf
}
适合:
stat(除非必须)如果你只需要:
d_type)if (entry->d_type == DT_DIR) { }
⚠️ 注意:
d_type 不可用openat + fd 避免路径拼接int dfd = open(dir, O_RDONLY);
int fd = openat(dfd, name, O_RDONLY);
优点:
realpath策略:
readdir⚠️ 注意:
readdir 不是线程安全的readdir_r 或自己加锁如果你必须 stat:
statx(Linux 4.11+)struct statx stx;
statx(fd, name, 0, STATX_SIZE | STATX_TYPE, &stx);
比 stat 快很多。
DIR *dir = opendir(path);
struct dirent *e;
while ((e = readdir(dir))) {
if (e->d_type == DT_REG)
process_file(e->d_name);
}
closedir(dir);
如果文件极多 → 改用 getdents64
readdir如果你能告诉我:
我可以给你针对性的代码模板。