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

如何使用C++ ifstream避免双缓冲读取/proc/self/smaps

问题:C++ ifstream read 是否存在双缓冲?

我原本用C语言读取/proc/self/smaps到缓冲区的代码(已简化,忽略错误处理,假设缓冲区足够):

char* buff = (char*)malloc(2 * 1024 * 1024); // 2MB 缓冲区
int fd = open("/proc/self/smaps", O_RDONLY);

char* buff_it = buff;
char* buff_end = buff_it + buff_sz - 1;
ssize_t read_sz;

while ((read_sz = read(fd, buff_it, buff_end - buff_it)) > 0)
   buff_it += read_sz;

close(fd);
// 解析 buff
free(buff);

现在改用C++的ifstream实现:

auto buff = std::make_unique<char[]>(2 * 1024 * 1024);
    
std::ifstream ifs("/proc/self/smaps", std::ios::binary);
ifs.read(buff.get(), 2 * 1024 * 1024); 
buff[ifs.gcount()] = '\0';

我的疑问是:ifstream的read函数内部会不会用一个私有缓冲区先存输入,再复制到我提供的缓冲区里?也就是这段代码是不是存在双缓冲?这会浪费资源。我希望ifstream直接用我提供的2MB缓冲区填充数据,关闭文件后再自行解析。


回答

默认情况下,std::ifstream确实会使用内部的缓冲区(由其关联的std::streambuf管理),这意味着你的代码会存在双缓冲:内核先把数据读到ifstream的内部缓冲区,之后read()再把数据从内部缓冲区复制到你提供的buff里,额外消耗了内存和复制开销。

要让ifstream直接使用你提供的缓冲区,有两种可行方案:

方案1:替换ifstream的内部缓冲区

你可以调用std::filebuf的pubsetbuf方法,指定自己的缓冲区作为ifstream的内部缓冲,示例代码如下:

auto buff = std::make_unique<char[]>(2 * 1024 * 1024);
const size_t buff_size = 2 * 1024 * 1024;

std::ifstream ifs;
ifs.rdbuf()->pubsetbuf(buff.get(), buff_size); // 设置自定义缓冲区
ifs.open("/proc/self/smaps", std::ios::binary);

// 读取全部内容到自定义缓冲区
ifs.read(buff.get(), buff_size);
buff[ifs.gcount()] = '\0';

注:pubsetbuf的行为在不同标准库实现中可能有细节差异,但主流实现(如GCC的libstdc++、Clang的libc++)都支持通过该方法替换内部缓冲区,完全避免双缓冲。

方案2:直接使用std::filebuf操作

如果不想依赖ifstream的上层封装,可以直接操作std::filebuf,更直接地控制缓冲区:

auto buff = std::make_unique<char[]>(2 * 1024 * 1024);
const size_t buff_size = 2 * 1024 * 1024;

std::filebuf fb;
if (fb.open("/proc/self/smaps", std::ios::in | std::ios::binary)) {
    fb.pubsetbuf(buff.get(), buff_size);
    // 读取数据直接写入自定义缓冲区
    std::streamsize bytes_read = fb.sgetn(buff.get(), buff_size);
    buff[bytes_read] = '\0';
    fb.close();
}

这种方式完全跳过ifstream的额外封装,确保没有多余的内部缓冲开销。

需要注意的细节:

  • 自定义缓冲区的生命周期必须长于std::ifstream或std::filebuf的生命周期,否则会出现悬空指针问题。
  • 对于/proc这类虚拟文件,其大小可能在读取过程中变化,但你已假设缓冲区足够,因此无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:15:28