2016-06-29 9 views
1

にメモリの変更を永続化する私のためにディスクへのメモリの変更を永続化します。私はファイルの特定のセクションをメモリにマップします。ファイルは円形のキューになります。私は、OSが変更されたページをディスクに書き込むようにすれば、より効率的であると考えていました。持つLinuxは、私はOS、Linuxが持つことができるかどうかを確認しようとしていたディスク

私は()、MSYNC()とと、munmap()はmmapに探し始めました。ポストの一つは、OSがすでにダーティページを追跡し、必要に応じてストレージにそれらをフラッシュするので、MSYNCのMS_ASYNC()は何もしませんことを示している

c linux msync(MS_ASYNC) flush order

ている:私は、次の記事を見つけました。それが何を意味するのかを正確に知っているといいでしょう。私はその会話の多くを理解していなかった

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)ディスクへの私のメモリ内の変化持続OSを持っている合理的な方法を使用していますか?

おかげで、 ニック

+0

まだ 'O_DIRECT'を試しましたか? –

+0

open()を呼び出すときにO_DIRECTを使用することを意味しますか?もしそうなら、いいえ。私は自分自身でそれをやっているのとは対照的に、OSが私のために変化を持続させる方法を見たいと思っています。 – nickdu

答えて

1

だからOSを持っている合理的な方法は、ディスクに私のメモリ内の変更を保持mmap()msync(MS_ASYNC)を使用していますか?

いいえ、そうではありません。

あなたのテストケースは、すべてのケースで、あなたのデータが安定したストレージに永続化されることを証明しない - あなたの狭いシナリオで表示されるように起こったことだけ。ちょうどdoesnのをセグメンテーションフォルトユーザランドプログラム - 人々がディスクに書き込まれたデータは、「クラッシュ」の顔に固執しているの話をするときさらに、彼らは通常、オペレーティングシステムやハードウェアの電力損失(例えばカーネルパニックなどオフ突然のパワー)のクラッシュを意味します実行中のカーネルがメモリ内で動いているダーティなデータにアクセス(さらには同期)することを止めることはできません。残念ながら、これはあなたのテストがあなたが必要とするものとは異なる何かを実証していたことを意味します。

としては、次のいずれかのデータが本当に安定したストレージにそれを作った場合に使用(との結果を確認してください)する必要があります知っているし、hereを述べた:

  • msync(MS_SYNC)
  • fsync
  • sync_file_range + fsync(メタデータ用)

あなたは決しての位置にいませんでした3210は、データが正常に永続化されたことを通知しないためです(Linuxでは、書き戻しが発生することを強制しません。これはリンク先のポストが警告するものです)。次のいずれかの

  • あなたは持続性を気にし、そのデータを永続安定したストレージに書き込まれ終了を持っていたときに知っておく必要があるが(例えば、あなたはそれがあるまで、他のアクションを延期したいです)。
  • システムが正常に動作している間に、そのデータのみが読み込み可能であれば大丈夫ですが、他のシナリオではそのデータが不確定であることは間違いありません。
関連する問題