当提升内存映射文件分配的磁盘空间超过HDD上的可用空间时,如何检测错误

How can detect error when boost memory mapped file allocated more disk space than is free on HDD

本文关键字:空间 错误 何检测 检测 HDD 映射 内存 文件分配 磁盘      更新时间:2023-10-16

在我的建模代码中,我使用boost内存映射文件来分配磁盘上的大型ish数组。

它工作得很好,但我找不到一种方法来检测我分配的数组大于磁盘drivw上可用空间的情况。例如,以下代码将愉快地执行(假设我在HDD上的可用空间小于8E9字节):

    boost::iostreams::mapped_file_params file_params;
    file_params.path = path;
    file_params.mode = std::ios::in | std::ios::out;
    file_params.new_file_size = static_cast<size_t>(8E9); # About 10GB
    file_params.length = static_cast<size_t>(8E9);
    boost::iostreams::mapped_file result;
    result.open(file_params);

我甚至可以在resuld.data()上工作,直到我写入未分配的部分内存(因为HDD上缺少空间),然后我得到以下错误:

 memory access violation at address: 0x7e9e2cd1e000: non-existent physical address

在我得到神秘的memory access violation之前,有什么方法可以检测到这个错误吗?

我实际上测试了这一点:如果文件大于分区上的可浏览可用空间,则代码会违反内存访问规则,如果文件较小,则代码可以工作(我通过更改分区上的可用空间而不是编辑代码来测试它)。

可能的解决方案

如果我的std:fill文件内容为零,我仍然会得到memory access violation,但这个错误位于分配附近,更容易调试。我宁愿想办法提出一个例外。

您可以使用fallocateposix_fallocate为文件预先预留空间。这样你就知道你永远不会"过度投入"。当然,在最初创建时,它有一个性能缺陷。

出于安全原因,操作系统可能会将fallocate上的块清零。

fallocate允许您进行未写入的扩展,但它在第一次访问时仍然为零。在windows上,可以使用SetFileValidData来解决这一问题。

请注意,带有O_DIRECT+fallocate()的Linux仍然使用相当大的CPU(与Windows的SetFileValidData相反),尽管IO带宽通常是瓶颈,但如果同时进行大量CPU工作,这仍然会对性能产生显著影响。

在我遇到神秘的内存访问违规之前,有什么方法可以检测到这个错误吗?

当您只更改文件的大小时,它将是sparse,这意味着没有数据的区域不会占用磁盘空间。空间是在写入过程中分配的,可能会造成磁盘空间不足的错误。

解决这个问题的一种方法是将(伪)数据写入文件,而不仅仅是更改大小。这需要更多的时间,但您只会在第一个写入周期内耗尽磁盘空间,因为文件在写入后会有最终大小。