温馨提示×

ubuntu怎么实现copendir

小樊
40
2026-08-17 22:49:29
栏目: 智能运维

在 Ubuntu(Linux)里,copendir 并不是标准 API,POSIX 只定义了:

  • opendir
  • readdir
  • closedir
  • rewinddir

如果你看到 copendir,通常是 某些项目或教材里的自定义函数,用于“复制一个已经打开的目录流(DIR*)”。

下面分几种情况说明 在 Ubuntu 下如何实现类似 copendir 的功能


一、为什么没有 copendir

DIR * 是一个 不透明结构体,标准并没有规定它的内部实现,因此:

  • 不能 memcpy
  • 不能简单复制指针
  • 不能保证线程安全

所以 POSIX 没有 copendir,只能自己实现。


二、最常见实现方式(推荐 ✅)

思路

dirfd() 获取目录 fd,然后 openat() + fdopendir()

这是 最干净、最安全、最推荐 的方式。

示例代码

#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

DIR *copendir(DIR *dirp) {
    if (!dirp)
        return NULL;

    int fd = dirfd(dirp);
    if (fd < 0)
        return NULL;

    int new_fd = openat(fd, ".", O_RDONLY | O_DIRECTORY);
    if (new_fd < 0)
        return NULL;

    return fdopendir(new_fd);
}

使用示例

DIR *dir1 = opendir("/tmp");
DIR *dir2 = copendir(dir1);

struct dirent *ent;
while ((ent = readdir(dir2)) != NULL) {
    printf("%s\n", ent->d_name);
}

closedir(dir1);
closedir(dir2);

✅ 优点:

  • 不依赖 DIR 内部结构
  • 符合 POSIX
  • 可用于多线程

三、另一种方式(不推荐 ⚠️)

重新 opendir 原路径

DIR *copendir(DIR *dirp) {
    char path[1024];
    snprintf(path, sizeof(path), "/proc/self/fd/%d", dirfd(dirp));
    return opendir(path);
}

⚠️ 缺点:

  • 依赖 /proc
  • 不是所有系统都有
  • 路径可能变化

四、如果你只是想“重新遍历目录”

其实 不需要 copendir,直接用:

rewinddir(dirp);

或者:

seekdir(dirp, 0);

✅ 适用于:

  • 单线程
  • 不需要同时遍历

五、总结

需求 推荐方案
复制 DIR* dirfd + openat + fdopendir
重新遍历 rewinddir
多线程 复制 DIR*
跨平台 复制 DIR*

如果你愿意,可以告诉我:

  • 你是 看到哪里的 copendir
  • 还是 自己想封装一个

我可以帮你写一个 完整可编译的 demo适配你项目的版本

0