让linux持久化内存更改到磁盘

问题描述 投票:1回答:1

我试图看看我是否可以拥有操作系统,linux,将内存更改保存到磁盘上。我会将文件的某些部分映射到内存中。该文件可以说是一个循环队列。我觉得如果我让操作系统处理将更改的页面写入磁盘会更有效率。

我开始研究mmap(),msync()和munmap()。我发现了以下文章:

c linux msync(MS_ASYNC) flush order

其中一个帖子表明msync()的MS_ASYNC是无操作,因为操作系统已经跟踪脏页并在必要时将它们刷新到存储器。很高兴知道这意味着什么。我也发现了这个:

msync() behaviour broken for MS_ASYNC, revert patch?

我不太了解那次谈话。我想我正在寻找一种有效的方法,即使在崩溃的情况下,我对内存表示中的更改也会持久保存到磁盘。

我在下面写了一个小样本应用程序。即使我引入崩溃,我写入映射内存的最新数据也会存储到磁盘中。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>

void main(int argc, char* argv[])
{
    int result;
    int fd = -1;

    if (argc != 2)
        {
        printf("Error, missing file name argument\n");
        goto done;
        }

    fd = open(argv[1], O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
    if (fd == -1)
        {
        printf("Failed opening file %s: %d\n", argv[1], errno);
        goto done;
        }

    unsigned int size = 8 * 1024L * 1024L;
    result = ftruncate(fd, size);
    if (result != 0)
        {
        printf("Failed setting file size: %d\n", errno);
        goto done;
        }

    void* addr;
    addr = mmap(NULL, size, PROT_WRITE, MAP_FILE | MAP_SHARED,
            fd, 0);
    if (addr == MAP_FAILED)
        {
        printf("Failed to map memory: %d\n", errno);
        goto done;
        }
    memset(addr, 'r', size);
    result = msync(addr, size, MS_ASYNC);
    getchar();
    if (result != 0)
        {
        printf("Failed syncing mapped memory: %d\n", errno);
        goto done;
        }
    memset(addr, 'p', size);
    getchar();

    memset(addr, 'm', size);

    // crash.

    *((int*) 0) = 0;

done:
    printf("done\n");
    if (fd != -1)
        close(fd);
    printf("closed file\n");
    return;
}

那么使用mmap(),msync(MS_ASYNC)是一种合理的方法让操作系统将内存中的更改保留在磁盘上吗?

谢谢,尼克

linux mmap
1个回答
1
投票

那么使用mmap()msync(MS_ASYNC)是一种合理的方法让操作系统将内存中的更改保留在磁盘上吗?

不,这不对。

您的测试用例并不能证明在任何情况下您的数据都会持久保存到稳定存储 - 只有在您的狭窄场景中才能看到它。此外,当人们谈到写入磁盘的数据在“崩溃”时持续存在时,他们通常意味着操作系统崩溃或硬件掉电(例如内核恐慌,突然断电等) - 一个用户态程序只是segfaulting doesn不要让正在运行的内核能够访问(甚至同步)在内存中滚动的脏数据。不幸的是,这意味着您的测试展示了与您需要的不同的东西。

如上所述here,要知道数据是否真正使其成为稳定存储,您必须使用(并检查结果)以下之一:

  • msync(MS_SYNC)
  • fsync
  • sync_file_range + fsync(元数据)

您永远无法使用msync(MS_ASYNC),因为它没有告诉您数据何时成功保留(并且在Linux上它甚至不会强制回写开始发生,这是您链接到的帖子警告的内容) 。或者:

  • 您关心持久性,并且您需要知道该数据何时完成写入持久稳定存储(例如,您希望推迟一些其他操作,直到它为止)。
  • 或者你不关心,你可以在系统继续正常运行时只读取数据,因此你可以确定这些数据在其他情况下是不确定的。
© www.soinside.com 2019 - 2024. All rights reserved.