2010-12-16 20 views
21

私は絶えず株価(int、longs、doubleなど)のファイルに追加しています。このファイルはmmapでメモリにマップされています。メモリマップされたファイルに追加する

新たに追加されたデータをメモリマッピングの一部として利用できる最も効率的な方法は何ですか?

ファイルをもう一度開いて(新しいファイルディスクリプタ)、新しいデータを取得するためにmmapすることができますが、それは効率が悪いようです。私に示唆されているもう1つのアプローチは、1MBのチャンクでファイルを事前に割り当て、最後に到達するまで特定の位置に書き込んだ後、ファイルを+ 1MBに変更します。

他の方法はありますか?

Doest Boostはこれを手助けしますか?

答えて

17

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がないようです。

いずれにせよ、あなたはもう一度だけmunmapそれをしてmmapて、ファイルを再度開く必要はありません。

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); 
} 

事前割り当て方式は、ここでは非常に有用である可能性があります。ファイルの実際の長さを記録してから、もう一度切り詰めて閉じてください。

14

私は答えがすでに受け入れられていることを知っていますが、もし私が答えを提供してくれれば、他の人を助けるでしょう。事前に大きなファイルを割り当てます。たとえば、10 GiBのサイズです。これら3つのファイルを事前に作成し、ボリュームと呼びます。ヘッダー、別のファイルなどのどこかで最後の既知の場所を追跡し、その時点から追加し続けます。あなたがファイルの最大サイズに達し、部屋を使い果たした場合、次の音量に切り替わります。それ以上のボリュームがない場合は、別のボリュームを作成します。新しいボリュームが作成されるのを待たずに追加をブロックしないように、これをいくつかのボリュームで先に実行することをお勧めします。これは私がDVRシステムに継続的に入ってくるビデオ/オーディオを監視のために保管するために働く場所です。実際のファイルシステムを使用していないため、フラットファイルになり、オフセット、フレーム情報(fps、フレームタイプ、幅/高さなど)だけを追跡するため、ビデオクリップのファイル名を格納するスペースを無駄にしません。 )、記録された時間およびカメラチャネル。あなたの記憶スペースは、あなたがやっている仕事の種類のために安いですが、あなたの時間は非常に貴重です。だから、前もって欲しいものを手に入れてください。基本的には、ニーズに合わせて最適化された独自のファイルシステムを実装しています。汎用ファイルシステムが必要とするのは、他の分野で必要とするニーズと同じではありません。

0

私の5セントですが、C固有のものです。 通常のファイルを作成しますが、mmapのサイズは大きくなります。たとえば、ファイルは100Kですが、mmapは1GB以上です。その後、ファイルサイズまですべてに安全にアクセスできます。ファイルサイズにアクセスするとエラーになります。 32ビットOSを使用している場合は、アドレス空間を食べるので、mmapを大きすぎないようにしてください。

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); 
} 
関連する問題