在 Debian(或任何 Linux)上调试 readdir 相关的问题,通常可以从系统调用、glibc 行为、文件系统、权限、程序逻辑几个层面入手。下面按常用方式给你一个比较系统的调试思路。
先明确一下:
readdir():glibc 对 getdents64 系统调用的封装readdir_r():已废弃,不推荐getdents() / getdents64():底层系统调用一般用户态程序用 readdir() 就够了。
这是最先该做的。
strace -f -e trace=openat,getdents64,readdir,stat,lstat ./your_program
或只关注目录读取:
strace -e trace=getdents64 ./your_program
常见观察点:
openat(dir) 是否成功getdents64() 返回多少字节ENOENT、EACCES、EMFILE示例:
openat(AT_FDCWD, "/tmp/test", O_RDONLY|O_DIRECTORY) = 3
getdents64(3, /* 10 entries */, 32768) = 320
如果你怀疑是程序逻辑问题:
gdb ./your_program
在 readdir 处打断点:
break readdir
run
查看返回值:
print dirp
print dirent->d_name
print errno
如果是 C++:
catch syscall getdents64
glibc 对 readdir 的错误信息有限,但可以:
export LIBC_FATAL_STDERR_=1
或者安装调试符号(Debian):
sudo apt install libc6-dbg
然后 GDB 里能看清 glibc 内部逻辑。
常见问题:
ls -ld /path/to/dir
ls -l /path/to/dir
x(执行)权限例如:
mount | grep path
某些文件系统对 readdir 有特殊行为:
可以换目录测试:
mkdir /tmp/test
touch /tmp/test/a /tmp/test/b
./your_program /tmp/test
C 示例:
DIR *d = opendir(path);
if (!d) {
perror("opendir");
return;
}
struct dirent *e;
while ((e = readdir(d)) != NULL) {
printf("%s\n", e->d_name);
}
if (errno) {
perror("readdir");
}
closedir(d);
注意:
readdir 不保证顺序这是正常的 POSIX 行为,不是 bug。
最小测试程序:
#include <dirent.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
DIR *d = opendir(argv[1]);
if (!d) { perror("opendir"); return 1; }
struct dirent *e;
while ((e = readdir(d)))
printf("%s\n", e->d_name);
closedir(d);
return 0;
}
gcc test.c -o test
./test /some/dir
你可以补充这些信息,我可以更具体地帮你:
如果你愿意,直接贴一段代码或 strace 输出,我可以帮你精确定位。