附加到内存映射文件

时间:2010-12-16 11:56:59

标签: c++ boost mmap

我不断追加股票报价(整数,多头,双打等)。我用mmap将此文件映射到内存中。

将新附加数据作为内存映射的一部分提供的最有效方法是什么?

据我所知,我可以再次打开文件(新文件描述符),然后对其进行mmap以获取新数据,但这似乎效率低下。我建议的另一种方法是以1mb块预先分配文件,写入特定位置直到到达结尾,然后将文件ftruncate为+ 1mb。

还有其他方法吗?

Doest对此有何帮助?

5 个答案:

答案 0 :(得分:22)

Boost.IOStreams只有固定大小memory mapped files,因此对您的具体问题没有帮助。 Linux有一个接口mremap,其工作方式如下:

void *new_mapping = mremap(mapping, size, size + GROWTH, MREMAP_MAYMOVE);
if (new_mapping == MAP_FAILED)
    // handle error
mapping = new_mapping;

然而,这是不可携带的(并且记录不完整)。 Mac OS X似乎没有mremap

在任何情况下,您都无需重新打开该文件,只需再次munmapmmap

void *append(int fd, char const *data, size_t nbytes, void *map, size_t &len)
{
    // TODO: check for errors here!
    ssize_t written = write(fd, data, nbytes);
    munmap(map, len);
    len += written;
    return mmap(NULL, len, PROT_READ, 0, fd, 0);
}

预分配方案在这里可能非常有用。请务必跟踪文件的实际长度,并在关闭之前再次将其截断。

答案 1 :(得分:16)

我知道答案已被接受,但如果我提供答案,它可能会帮助其他人。提前分配一个大文件,比如说大小为10 GiB。提前创建其中三个文件,我称之为卷。跟踪您在标题,其他文件等位置的最后已知位置,然后继续追踪该点。如果达到文件的最大大小并且没用房间,请切换到下一个卷。如果没有更多卷,请创建另一个卷。请注意,您可能会提前几卷,以确保不会阻止您的附加等待创建新卷。这就是我们在DVR系统中用于存储连续传入视频/音频以进行监视的方法。我们不会浪费空间来存储视频剪辑的文件名,这就是为什么我们不使用真正的文件系统,而是我们去平面文件,我们只是跟踪偏移,帧信息(fps,帧类型,宽度/高度等) ),时间记录和相机频道。对于您来说,存储空间对于您正在进行的工作来说是便宜的,而您的时间非常宝贵。所以,尽可能多地抓住你想要的东西。您基本上是在实现自己的文件系统,以满足您的需求。通用文件系统提供的需求与我们在其他领域所需的需求不同。

答案 2 :(得分:2)

man page for mremap它应该是可能的。

答案 3 :(得分:0)

我的5,但它们更具C特异性。 制作普通文件,但mmap庞大 - 例如文件说100K,但mmap 1GB或更多。然后,您可以安全地访问文件大小的所有内容。访问文件大小将导致错误。 如果你使用的是32位操作系统,只是不要让mmap太大,因为它会占用你的地址空间。

答案 4 :(得分:0)

如果您在Windows上使用boost/iostreams/device/mapped_file.hpp

如果读取映射对象由于缺少共享权限而打开,则

boost::filesystem::resize_file会抛出异常。 相反,使用windows-api调整光盘上的文件大小,读取mapped_file仍然可以打开。

bool resize_file_wapi(string path, __int64 new_file_size) //boost::uintmax_t size
{
    HANDLE handle = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0);
    LARGE_INTEGER sz;
    sz.QuadPart = new_file_size;

    return handle != INVALID_HANDLE_VALUE
    && ::SetFilePointerEx(handle, sz, 0, FILE_BEGIN)
    && ::SetEndOfFile(handle)
    && ::CloseHandle(handle);
}