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

时间:2016-06-29 03:11:54

标签: linux mmap

我试图看看我是否可以拥有操作系统,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)是一种合理的方法让操作系统将内存中的更改保留在磁盘上吗?

谢谢, 尼克

1 个答案:

答案 0 :(得分:1)

  

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

不,不是。

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

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

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

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

  • 您关心持久性,并且您需要知道该数据何时已完成被写入持久性稳定存储(例如,您希望推迟其他一些操作)。
  • 或者您不在乎,只有在系统继续正常运行时才能读取这些数据,您就可以了,因此您可以在其他情况下确定该数据是不确定的。