在 CentOS(以及一般 Linux)上,readdir 本身是由内核和 glibc 实现的,应用程序不能直接“缓存 readdir”,但可以从系统层、库层、应用层多个角度来做目录读取缓存。下面按常见场景说明。
readdir 调用路径大致是:
应用 (readdir)
-> glibc
-> getdents / getdents64 (syscall)
-> 内核 VFS
-> 文件系统 (ext4/xfs/nfs/overlay 等)
缓存可能存在于:
CentOS 默认会缓存目录项:
cat /proc/sys/vm/vfs_cache_pressure
100调优(谨慎):
sysctl -w vm.vfs_cache_pressure=50
⚠ 不建议设为 0,可能导致内存压力
第一次 ls 或 readdir 后,内核会缓存:
ls /path/to/dir # 预热
重复访问会明显变快。
如果是 NFS 目录,readdir 很慢,需要专门缓存。
mount -o actimeo=600,nocto nfs-server:/dir /mnt
参数说明:
actimeo=600:属性和目录缓存 600 秒nocto:减少 close-to-open 一致性检查查看:
cat /proc/mounts | grep nfs
OverlayFS 的 readdir 性能依赖底层文件系统缓存。
可尝试:
mount -o redirect_dir=on,index=on overlay
如果你的程序频繁调用 readdir,最可靠的是自己缓存。
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
char **cached_dir(const char *path) {
DIR *d = opendir(path);
struct dirent *e;
char **list = malloc(sizeof(char*) * 1000);
int n = 0;
while ((e = readdir(d))) {
list[n++] = strdup(e->d_name);
}
closedir(d);
list[n] = NULL;
return list;
}
然后自己控制刷新策略(如 10 秒、文件变更监听)。
只是遍历工具,不缓存。
inotifywait -m /path/to/dir
目录变化时才刷新缓存。
getenforce
如果是 Enforcing,每次访问可能有策略检查开销。
| 场景 | 推荐做法 |
|---|---|
| 本地目录 | 依靠内核 dentry 缓存 |
| NFS | mount 参数 + actimeo |
| 高频 readdir | 应用层缓存 |
| 容器 | overlay 底层缓存 |
| 极致性能 | readdir + 自建缓存 + inotify |
如果你能说明:
我可以给你更具体的缓存方案或代码示例。