You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中从/proc目录复制文件的最优安全方法(std::filesystem::copy_file失效)

解决C++中复制/proc/self/mountinfo的问题

/proc下的文件是内核提供的虚拟文件,并非磁盘上的常规实体文件,std::filesystem::copy_file()依赖常规文件的元数据和I/O逻辑,因此无法直接处理这类虚拟文件。除了手动打开文件读取再写入的方式,还有两种简单安全的实现方案:

方案一:C标准库流式分块拷贝(跨平台通用)

这种方式本质仍是文件读写,但通过分块读取避免一次性加载全部内容到内存,更安全高效,代码也简洁易维护:

#include <cstdio>
#include <stdexcept>

void copy_proc_file(const char* src_path, const char* dest_path) {
    FILE* src = std::fopen(src_path, "r");
    if (!src) {
        throw std::runtime_error("无法打开源文件");
    }

    FILE* dest = std::fopen(dest_path, "w");
    if (!dest) {
        std::fclose(src);
        throw std::runtime_error("无法打开目标文件");
    }

    char buffer[4096];
    size_t bytes_read;
    while ((bytes_read = std::fread(buffer, 1, sizeof(buffer), src)) > 0) {
        if (std::fwrite(buffer, 1, bytes_read, dest) != bytes_read) {
            std::fclose(src);
            std::fclose(dest);
            throw std::runtime_error("写入目标文件失败");
        }
    }

    if (std::ferror(src)) {
        std::fclose(src);
        std::fclose(dest);
        throw std::runtime_error("读取源文件失败");
    }

    std::fclose(src);
    std::fclose(dest);
}

// 使用示例
int main() {
    try {
        copy_proc_file("/proc/self/mountinfo", "/tmp/mountinfo_copy");
    } catch (const std::exception& e) {
        // 这里可以添加错误日志或用户提示
        return 1;
    }
    return 0;
}

方案二:Linux系统调用copy_file_range(性能最优)

如果程序仅需在Linux环境运行,copy_file_range是内核提供的高效拷贝系统调用,能直接在内核空间完成数据传输,避免用户态与内核态的多次切换,性能更优,且支持虚拟文件的拷贝:

#include <fcntl.h>
#include <unistd.h>
#include <stdexcept>
#include <cstdint>

void copy_proc_file(const char* src_path, const char* dest_path) {
    int src_fd = open(src_path, O_RDONLY);
    if (src_fd == -1) {
        throw std::runtime_error("无法打开源文件");
    }

    int dest_fd = open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dest_fd == -1) {
        close(src_fd);
        throw std::runtime_error("无法打开目标文件");
    }

    off64_t src_offset = 0;
    off64_t dest_offset = 0;
    ssize_t bytes_copied;
    while ((bytes_copied = copy_file_range(src_fd, &src_offset, dest_fd, &dest_offset, 4096, 0)) > 0) {
        // 循环直到拷贝完成
    }

    if (bytes_copied == -1) {
        close(src_fd);
        close(dest_fd);
        throw std::runtime_error("文件拷贝失败");
    }

    close(src_fd);
    close(dest_fd);
}

// 使用示例
int main() {
    try {
        copy_proc_file("/proc/self/mountinfo", "/tmp/mountinfo_copy");
    } catch (const std::exception& e) {
        // 这里可以添加错误日志或用户提示
        return 1;
    }
    return 0;
}

关键注意事项

  • 虚拟文件的大小通常显示为0,但实际可读取到有效内容,因此不能依赖文件大小判断读取终点,必须循环读取直到EOF。
  • 两种方案都包含完整的错误处理,确保文件描述符/指针被正确关闭,避免资源泄漏。

内容的提问来源于stack exchange,提问作者bun9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:24:19