4

私はメモリマップトファイルについて読んでいます。ソースは、ファイルを開いたり、システムコールを開いたり読んだりする方法を説明せずに、システムコールを開く、システムコールを読むなどのファイルを読み取る方が従来の方法よりも速いと言っています。

では、オープンシステムコールがどのように機能するのかという私の質問 です。

私の知る限り、ファイルはメモリにロードされますが、マップされたファイルを使用すると、アドレスのみがメモリに保存され、必要に応じて要求されたページがメモリに取り込まれる可能性があります。

これまでの理解を明確にすることを期待しています。

編集

上に書いた私の以前の理解はほとんど間違っています。正しい説明については、Pawelによって受け入れられた答えを参照してください。

4

3 に答える 3

8

あなたが詳細を与えなかったので、私はあなたがUnixライクなシステムの振る舞いに興味があると思います。

実際open()には、システムコールはファイル記述子のみを作成し、それをまたはのいずれかで使用できmmap()ますread()

メモリマップドI/Oと標準I/Oはどちらも、I / O操作の数を減らすためにファイルがキャッシュされるバッファであるページキャッシュを介して、ディスク上のファイルに内部的にアクセスします。

標準のI/Oアプローチ(write()およびを使用read())では、システムコールを実行し、ページキャッシュから(または書き込み中の場合は)アプリケーションによって選択されたバッファーにデータをコピーします。その非順次アクセスに加えて、別のシステムコールが必要lseek()です。システムコールは高額であり、データのコピーも高額です。

ファイルがメモリマップされる場合、通常、プロセスアドレス空間のメモリ領域はページキャッシュに直接マップされるため、すでにロードされているデータのすべての読み取りと書き込みを追加の遅延なしで実行できます(システムコールやデータコピーは不要)。アプリケーションがまだロードされていないファイル領域にアクセスしようとした場合にのみ、ページフォールトが発生し、カーネルが必要なデータ(ページ全体)をディスクからロードします。

編集:メモリページング についても説明する必要があることがわかります。最新のアーキテクチャのほとんどには、実際のハードウェアである物理メモリと、プロセスのアドレス空間を作成する仮想メモリがあります。カーネルは、仮想メモリ内のアドレスを物理メモリ内のアドレスにマップする方法を決定します。最小単位はメモリページです(通常、ただし常に4Kであるとは限りません)。1:1マッピングである必要はありません。たとえば、すべての仮想メモリページを同じ物理アドレスにマッピングできます。

メモリマップドI/Oでは、アプリケーションのアドレス空間とカーネルのページキャッシュが同じ物理メモリ領域にマップされるため、プログラムはページキャッシュに直接アクセスできます。

于 2012-10-07T14:59:15.347 に答える
4

Pawelは、読み取り/書き込みの実行方法を美しく説明しています。元の質問を説明しましょう:fopen(3)はどのように機能しますか:ユーザースペースプロセスがfopen(libcまたは任意のユーザースペースライブラリで定義されている)に遭遇すると、それをopen(2)システムコールに変換します。まず、fopenから引数を取り、open()システムコール番号とともにアーキテクチャ固有のレジスタに書き込みます。この番号は、システムコールユーザースペースプログラムが実行したいことをカーネルに通知します。これらのレジスタをロードした後、ユーザースペースプロセスはカーネル(softirq従来はx86上のINT 80Hを介して)とブロックを中断します。

カーネルは、提供された引数やアクセス許可などを確認してから、エラーを返すかvfs_open()、この場合は実際のシステムコールを呼び出します。vfs_open()fd配列で使用可能なファイル記述子をチェックし、構造体ファイルを割り当てます。アクセスされたファイルの参照カウントが増加し、fdがユーザープログラムに返されます。これで、オープンの作業、および一般的なほとんどのシステムコールの作業が完了しました。

open()read()/と一緒にwrite()、その後に続くのclose()は、メモリマップトファイルをバッファキャッシュに入れるよりも間違いなく非常に長いプロセスです。

于 2016-02-26T03:50:08.927 に答える
0

Linuxでオープンと読み取りがどのように機能するかについての明確な説明については、これを読むことができます。コードスニペットは古いバージョンのカーネルからのものですが、理論は依然として当てはまります。

有効なファイル記述子を取得するには、open()システムコールを使用する必要があります。この記述子をmmap()に渡します。mmaped IOが高速である理由については、読み取りおよび書き込みシステムコールで発生する、ユーザースペースからカーネルスペースバッファーへのデータのコピーがないためです。

于 2012-10-07T15:05:19.173 に答える