在 Linux 下,readdir()(以及 readdir_r())本身是一个阻塞式的库函数,它没有内建的“中断参数”,所以从 API 层面来说,你不能直接“传一个标志”让它中途返回。
但可以从系统/编程模型层面来实现“中断 readdir”。下面按常见场景说明。
readdir() 底层通常调用:
getdents() / getdents64()(syscall)如果目录:
就可能长时间阻塞。
pthread_cancel(不推荐但可行)pthread_t tid;
pthread_create(&tid, NULL, scan_dir, dir);
// 想中断时
pthread_cancel(tid);
pthread_join(tid, NULL);
⚠ 注意:
readdir() 是 cancellation pointpthread_cleanup_pushopendir + 超时(推荐)思路:
pthread_join(timeout)void* worker(void* arg) {
DIR* d = opendir(path);
struct dirent* e;
while ((e = readdir(d))) {
// 处理
}
closedir(d);
return NULL;
}
主线程:
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 5;
pthread_t t;
pthread_create(&t, NULL, worker, NULL);
pthread_timedjoin_np(t, NULL, &ts); // 超时则放弃
open() + getdents() + select/poll(高级)如果你自己实现目录读取:
int fd = open(path, O_RDONLY | O_DIRECTORY);
但:
getdents() 仍然阻塞select() 不能用于普通目录 fd✅ 解决:
alarm() + SIGALRM(不推荐)signal(SIGALRM, handler);
alarm(5);
readdir(dir);
问题:
readdir 可能自动重启(SA_RESTART)stat() 先判断fts_open() / nftw() 并加超时控制✅ 推荐结构:
while ((e = readdir(dir))) {
if (stop_flag) break;
}
但如果你已经卡在 readdir 内部,这个 flag 没用。
| 方法 | 是否推荐 | 说明 |
|---|---|---|
| pthread_cancel | ❌ | 易泄漏 |
| 线程 + 超时 | ✅ | 最常用 |
| io_uring | ✅✅ | 现代方案 |
| signal | ❌ | 不稳定 |
| flag 变量 | ⚠ | 只能未阻塞时用 |
如果你能说明:
我可以给你具体可编译的示例。