在 CentOS(本质是 Linux 的 readdir 系列调用) 里,readdir / readdir_r / scandir 确实有一些“坑”和容易踩雷的地方,尤其在高并发、大目录、跨版本、C/C++ 开发中很常见。下面按实际踩坑频率给你总结一下。
多线程同时调用同一个 DIR*:
DIR *dir = opendir(path);
readdir(dir); // ❌ 多线程共用
会导致:
opendirreaddir_r(但见下一条)直接用
readdir(),但保证 一个 DIR 只被一个线程使用*
readdir 非常慢✅ 拆分目录(hash / 日期)
✅ 用数据库 / 对象存储
✅ 避免 ls 大目录
以为 readdir 是按文件名排序的
✅ 需要排序要自己 sort
struct dirent *de = readdir(dir);
de->d_ino == 0; // 某些网络文件系统
d_ino == 0de->d_type == DT_REG
d_type == DT_UNKNOWNif (de->d_type == DT_UNKNOWN) {
stat(path, &st);
}
char *names[100];
struct dirent *de;
while ((de = readdir(dir))) {
names[i++] = de->d_name; // ❌
}
readdir 返回的是同一块静态内存names[i++] = strdup(de->d_name);
DIR *dir = opendir(path);
readdir(dir); // path 不存在直接崩
✅ 必须:
if (!dir) {
perror("opendir");
}
| CentOS | glibc | 注意 |
|---|---|---|
| 6 | 2.12 | readdir_r 安全 |
| 7 | 2.17 | 还能用 |
| 8+ | 2.28+ | readdir_r deprecated |
readdir 不解析符号链接DIR *dir = opendir(path);
if (!dir) return;
struct dirent *de;
while ((de = readdir(dir))) {
if (de->d_name[0] == '.') continue;
if (de->d_type == DT_UNKNOWN) {
// stat
}
}
closedir(dir);
CentOS 上 readdir 最大的坑不是 API 本身,而是:线程安全、顺序、d_type、内存复用、目录规模。
如果你愿意,我可以:
你现在是 C / C++ / Python / shell 场景?