質問

グーグルで検索したところ、ほとんどの人が次の使用を推奨していることがわかりました。 kmalloc, 連続した物理ブロックのメモリを取得できることが保証されているためです。ただし、次のようにも思えます kmalloc 連続している場合は失敗する可能性があります 物理的な 必要なブロックが見つかりません。
メモリのブロックが連続していることの利点は何ですか?具体的には、なぜ連続した 物理的な メモリのブロック システムコール?使えない理由があったのか vmalloc?
最後に、システム コールの処理中にメモリを割り当てる場合、次のように指定する必要がありますか? GFP_ATOMIC?システムコールはアトミックコンテキストで実行されますか?

GFP_ATOMIC
割り当ては優先度が高く、眠りません。これは、割り込みハンドラー、底の半分、および眠れないその他の状況で使用するフラグです。

GFP_KERNELこれは通常の割り当てであり、ブロックされる可能性があります。これは、睡眠が安全であるときにプロセスコンテキストコードで使用するフラグです。

役に立ちましたか?

解決

物理的にアドレス指定されたバス (PCI など) 上の DMA デバイスによってバッファにアクセスされる場合にのみ、物理的に連続したメモリの使用を考慮する必要があります。問題は、多くのシステム コールでは、バッファが最終的に DMA デバイスに渡されるかどうかを知る方法がないことです。バッファを別のカーネル サブシステムに渡すと、そのバッファがどこに送られるのかはまったくわかりません。カーネルが DMA にバッファを使用しない場合でも 今日、 将来の開発ではそうなる可能性があります。

vmalloc は、バッファー領域を仮想的に連続した範囲に再マップする必要がある場合があるため、多くの場合 kmalloc よりも遅くなります。kmalloc は再マップしませんが、GFP_ATOMIC で呼び出されない場合、kmalloc はブロックされる可能性があります。

kmalloc が提供できるバッファのサイズには制限があります。128キロバイト*). 。本当に大きなバッファが必要な場合は、vmalloc または起動時に高メモリを予約するなどの他のメカニズムを使用する必要があります。

*) これは以前のカーネルにも当てはまりました。最近のカーネル (私は 2.6.33.2 でテストしました) では、1 つの kmalloc の最大サイズは最大 4 MB です。(適当に書きました これに関する詳細な投稿.) — カイワン

システムコールの場合、GFP_ATOMIC を kmalloc() に渡す必要はなく、GFP_KERNEL を使用できます。あなたは割り込みハンドラーではありません。アプリケーション コードはトラップによってカーネル コンテキストに入りますが、これは割り込みではありません。

他のヒント

短い答え:ダウンロード Linuxデバイスドライバー そしてメモリ管理に関する章を読んでください。

真剣に言うと、カーネルのメモリ管理に関連して理解する必要がある微妙な問題がたくさんあります。私は問題のデバッグに多くの時間を費やしています。

カーネルが仮想メモリを使用することはほとんどないため、vmalloc() が使用されることはほとんどありません。kmalloc() は通常使用されるものですが、さまざまなフラグの結果が何であるかを知る必要があり、特にあなたが提案したように、割り込みハンドラー内にある場合には、失敗したときに何が起こるかに対処する戦略が必要です。

Robert Love 著の『Linux Kernel Development』 (第 3 版の第 12 章、244 ページ) はこれに非常に明確に答えています。

はい、多くの場合、物理的に連続したメモリは必要ありません。カーネルで vmalloc よりも kmalloc が使用される主な理由はパフォーマンスです。この本では、vmalloc を使用して大きなメモリ チャンクが割り当てられる場合、カーネルは物理的に連続していないチャンク (ページ) を単一の連続した仮想メモリ領域にマップする必要があると説明しています。メモリは仮想的には連続していますが、物理的には非連続であるため、いくつかの仮想アドレスから物理アドレスへのマッピングをページ テーブルに追加する必要があります。そして最悪の場合には、 (バッファサイズ/ページサイズ) ページテーブルに追加されるマッピングの数。

これにより、このバッファにアクセスするときに TLB (最近の仮想アドレスから物理アドレスへのマッピングを保存するキャッシュ エントリ) への負荷も高まります。これにより次のような問題が発生する可能性があります スラッシング.

kmalloc() & vmalloc() 関数は、カーネル メモリをバイト サイズのチャンクで取得するための単純なインターフェイスです。

  1. kmalloc() 関数は、ページが物理的に連続している (および仮想的に連続している) ことを保証します。

  2. vmalloc() 関数は同じように動作します kmalloc(), ただし、仮想的にのみ連続しており、必ずしも物理的に連続しているわけではないメモリが割り当てられます。

メモリのブロックが連続していることの利点は何ですか?具体的には、システム コールで連続した物理メモリ ブロックが必要になるのはなぜでしょうか?vmalloc を使用できない理由はありますか?

Google の「I'm Feeling Lucky」より vmalloc:

非常に大きな領域が必要でない限り、kmalloc が推奨される方法です。問題は、ハードウェア デバイスとの間で DMA を実行したい場合、kmalloc を使用する必要があり、おそらくより大きなチャンクが必要になることです。解決策は、メモリが断片化される前に、できるだけ早くメモリを割り当てることです。

32 ビット システムでは、 kmalloc() は、物理アドレスへの直接マッピング (実際には一定のオフセットを持つ) を持つカーネル論理アドレス (ただし、仮想アドレス) を返します。この直接マッピングにより、RAM の連続した物理チャンクが確実に取得されます。初期ポインタのみを与え、その後の操作で連続した物理マッピングを期待する DMA に適しています。

vmalloc() はカーネル仮想アドレスを返しますが、このアドレスは物理 RAM 上に連続したマッピングを持たない可能性があります。大規模なメモリ割り当ての場合や、プロセスに割り当てられたメモリが物理 RAM 内でも連続していることを気にしない場合に便利です。

その他の違いの 1 つは、kmalloc が論理アドレスを返すことです (それ以外の場合は GPF_HIGHMEM を指定します)。論理アドレスは「低メモリ」(物理メモリの最初のギガバイト) に配置され、物理アドレスに直接マップされます (変換するには __pa マクロを使用します)。このプロパティは、kmalloced メモリが連続メモリであることを意味します。

一方、Vmalloc は「ハイ メモリ」から仮想アドレスを返すことができます。これらのアドレスを直接物理アドレスに変換することはできません (virt_to_page 関数を使用する必要があります)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top