まず、コードのこの部分を asm 、espで記述しないでください。最初ではありません。この部分を処理する C 関数を作成し、asm から呼び出します。別の 16MiB をダンプするときにのみ実行される部分をパフォーマンス調整する必要がある場合は、手動で調整できます。システムレベルのプログラミングは、システムコール (または C stdio 関数) からのエラーリターンをチェックすることがすべてであり、asm でそれを行うのは面倒です。
システム コールの作成は C と比較して特別なことではないため、明らかに asm で何でも記述できます。また、C と比較して asm の方が簡単な部分はありませんMFENCE。
とにかく、私はあなたがバッファで何をしたいのかについて3つのバリエーションに対処しました:
- 同じバッファを上書きします (
mmap(2)/ msync(2))
- バッファーのスナップショットをファイルに追加します (
write(2)またはおそらく機能しないゼロコピーvmsplice(2)+splice(2)アイデアを使用して)。
- 古いバッファを書き込んだ後、新しい (ゼロ化された) バッファを開始します。
mmap(2)出力ファイルの順次チャンク。
インプレース上書き
毎回ディスクの同じ領域を上書きしたい場合はmmap(2)、ファイルを作成して、それをアレイとして使用します。(データを強制的にディスクに書き込むために定期的に呼び出しmsync(2)ます。) ただし、mmapped メソッドは、ファイルの一貫した状態を保証しません。書き込みは、要求があった場合以外にディスクにフラッシュされる可能性があります。何らかの保証でそれを回避する方法がある場合はIDK(つまり、バッファフラッシュタイマーなどを選択するだけでなく、通常、msync(2).
スナップショットを追加
バッファをファイルに追加する簡単な方法は、書き込みたいときに呼び出すだけwrite(2)です。 write(2)必要なすべてを行います。プログラムがマルチスレッドの場合、システム コールの前にデータをロックし、後でロックを解除する必要がある場合があります。write システム コールがどれだけ速く返されるかはわかりません。カーネルがデータをページキャッシュにコピーした後にのみ返される場合があります。
スナップショットが必要なだけで、バッファへのすべての書き込みがアトミック トランザクションである場合 (つまり、互いに一貫性を保つ必要がある値のペアではなく、バッファが常に一貫した状態にある場合)、スナップショットを取得する必要はありません。を呼び出す前にロックしwrite(2)ます。この場合、わずかな偏りがあります (カーネルが順番にコピーすると仮定すると、バッファーの最後のデータは最初のデータよりも少し後の時間からのものになります)。
write(2)ダイレクト IO (ゼロコピー、ページキャッシュのバイパス) で IDKが遅くなったり速くなったりする場合。open(2)あなたのファイルはO_DIRECT、write(2)通常は.
バッファのスナップショットを書き込んで変更し続ける場合は、プロセスのどこかにコピーが必要です。または、MMU コピー オン ライトのトリック:
ゼロコピー追加スナップショット
ユーザーページのディスクファイルへのゼロコピー書き込みを行うための API があります。Linux のvmsplice(2)とsplice(2)この順序で、ページをページ キャッシュにマップするようにカーネルに指示できます。がなければSPLICE_F_GIFT、コピーオンライトとして設定すると思います。(おっと、実際にはmanページには without と書かれていますがSPLICE_F_GIFT、以下splice(2)はコピーする必要があります。したがって、コピーオンライトセマンティクスを取得するメカニズムがある場合はIDKです。)
カーネルがディスクへの書き込みを完了して解放できるようになるまで、ページのコピー オン ライト セマンティクスを取得する方法があると仮定します。
さらに書き込みを行うには、データがディスクにヒットする前にカーネルが 1 ページまたは 2 ページを memcpy する必要があるかもしれませんが、バッファー全体をコピーする必要はありません。ソフト ページ フォールトとページ テーブル操作のオーバーヘッドは、書き込みがディスクにヒットし、書き込み対象のページが解放されるまでの短い期間にデータ アクセス パターンが非常に空間的に局所化されていない限り、いずれにしても価値がない可能性があります。(このように動作する API は存在しないと思います。なぜなら、ページがディスクにヒットした直後にページを解放するメカニズムがないからです。Linux はそれらを引き継いで、ページ キャッシュに保持したいと考えています。)
私は vmsplice を使用したことがないので、詳細が間違っている可能性があります。
同じメモリの新しいコピー オン ライト マッピングを作成する方法がある場合、おそらくmmapスクラッチ ファイル (tmpfs ファイル システム上) の新しいマッピングを作成することによって/dev/shm、ロックを長時間保持せずにスナップショットを取得できます。 . 次に、スナップショットを に渡すだけでwrite(2)、コピー オン ライト ページ フォールトが多く発生する前にできるだけ早くマップを解除できます。
チャンクごとに新しいバッファ
すべての書き込み後にバッファをゼロにして開始しても問題ない場合mmap(2)は、ファイルの連続したチャンクを作成できるため、生成するデータは常に適切な場所にあります。
- (オプション)
fallocate(2)書き込みパターンがシーケンシャルでない場合に断片化を防ぐために、出力ファイルにいくらかのスペース。
mmap(2)出力ファイルの最初の 16MiB にバッファを追加します。
- 普通に走る
- 次の 16MiB に移動する場合:
- ロックを取得して、他のスレッドがバッファを使用できないようにする
munmap(2)あなたのバッファ
mmap(2)ファイルの次の 16MiB を同じアドレスに転送するため、新しいアドレスをライターに渡す必要はありません。これらのページは、POSIX の要求に応じて事前にゼロ化されます (カーネルがメモリを公開することはできません)。
- ロックを解除する
おそらく/ペア mmap(buf, 16MiB, ... MAP_FIXED, fd, new_offset)を置き換えることができます。重複する古いイングを破棄します。これは、ファイル/共有メモリへの変更が破棄されることを意味するのではなく、実際のマッピングが変更されることを意味すると思います。munmapmmapMAP_FIXEDmmapmunmap