21

私の C++ プログラム (Windows 上) では、メモリのブロックを割り当てており、物理メモリ内で (つまり、VirtualAllocEx()、MapUserPhysicalPages() などを使用して) ロックされたまま (スワップされておらず、連続している) であることを確認できます。

私のプロセスのコンテキストでは、そのブロックの VIRTUAL メモリ アドレスを取得できますが、 外部デバイスに渡すために、そのブロックの PHYSICAL メモリ アドレスを見つける必要があります。


1. USER モードで、プログラム内で仮想アドレスを物理アドレスに変換する方法はありますか?

2.そうでない場合、この仮想から物理へのマッピングは KERNEL モードでのみ見つけることができます。私はそれを行うためにドライバーを書かなければならないことを意味していると思います...?私のアプリケーション (プログラム) が変換を行うために使用できる、すぐに利用できるドライバー/DLL/API を知っていますか?

3.ドライバーを自分で書かなければならない場合、どのように変換すればよいですか? どの機能を使用しますか? mmGetPhysicalAddress()ですか?どうやって使うの?

4.また、私の理解が正しければ、 mmGetPhysicalAddress() は、呼び出しプロセスのコンテキストにある仮想ベース アドレスの物理アドレスを返します。ただし、呼び出しプロセスがドライバーであり、アプリケーションを使用してその関数のドライバーを呼び出している場合、コンテキストを変更していて、mmGetPhysicalAddress ルーチンが呼び出されたときにアプリのコンテキストにいることはできません...ドライバーではなく、アプリケーション (ユーザーモード) のメモリ空間で仮想アドレスを変換するにはどうすればよいですか?

回答、ヒント、コードの抜粋は大歓迎です!!

ありがとう

4

6 に答える 6

12

私の C++ プログラム (Windows 上) では、メモリのブロックを割り当てており、物理メモリ内で (つまり、VirtualAllocEx()、MapUserPhysicalPages() などを使用して) ロックされたまま (スワップされておらず、連続している) であることを確認できます。

いいえ、ロックされていることを保証することはできません。プロセスがクラッシュしたり、早期に終了した場合はどうなりますか? ユーザーがそれを殺した場合はどうなりますか?そのメモリは別の用途に再利用され、デバイスがまだ DMA を実行している場合、最終的にデータの損失/破損またはバグチェック (BSOD) が発生します。

また、MapUserPhysicalPagesWindows Server の 32 ビット バージョンで 4 GB を超える RAM を処理するための Windows AWE (Address Windowing Extensions) の一部です。ユーザーモードの DMA をハッキングするために使用することを意図したものではないと思います。

1. USER モードで、プログラム内で仮想アドレスを物理アドレスに変換する方法はありますか?

これを可能にするドライバーはありますが、Windows のユーザー モードから DMA をプログラムすることはできず、安定した安全なシステムを維持できます。制限付きユーザー アカウントとして実行されるプロセスに物理メモリの読み取り/書き込みを許可すると、そのプロセスがシステムを所有できるようになります。これが 1 回限りのシステムまたはプロトタイプ用である場合、これはおそらく許容されますが、他の人 (特に有料の顧客) があなたのソフトウェアとデバイスを使用することを期待する場合は、ドライバーを作成する必要があります。

2. そうでない場合、この仮想から物理へのマッピングは KERNEL モードでのみ見つけることができます。私はそれを行うためにドライバーを書かなければならないことを意味していると思います...?

これは、この問題に取り組むための推奨される方法です。

私のアプリケーション (プログラム) が変換を行うために使用できる、すぐに利用できるドライバー/DLL/API を知っていますか?

MDL (メモリ記述子リスト)を使用して、ユーザー モード プロセスが所有するメモリ バッファーを含む任意のメモリをロックダウンし、その仮想アドレスを物理アドレスに変換できます。またはDeviceIoControlを使用して、への呼び出しに渡されたバッファの MDL を Windows で一時的に作成することもできます。METHOD_IN_DIRECTMETHOD_OUT_DIRECT

仮想アドレス空間の連続したページが、物理アドレス空間で連続することはほとんどないことに注意してください。お使いのデバイスがそれを処理できるように設計されていることを願っています。

3. ドライバーを自分で書かなければならない場合、どのように変換すればよいですか? どの機能を使用しますか? mmGetPhysicalAddress()ですか?どうやって使うの?

ドライバーを作成するには、いくつかの API を呼び出すだけではありません。ドライバーを作成する場合は、 MSDNおよびOSRからできるだけ多くの関連資料を読むことをお勧めします。また、Windows Driver Kitの例も参照してください。

4. また、私の理解が正しければ、mmGetPhysicalAddress() は、呼び出しプロセスのコンテキストにある仮想ベース アドレスの物理アドレスを返します。ただし、呼び出しプロセスがドライバーであり、アプリケーションを使用してその関数のドライバーを呼び出している場合、コンテキストを変更していて、mmGetPhysicalAddress ルーチンが呼び出されたときにアプリのコンテキストにいることはなくなります...ドライバーではなく、アプリケーション (ユーザーモード) のメモリ空間で仮想アドレスを変換するにはどうすればよいですか?

ドライバーはプロセスではありません。ドライバーは、さまざまな昇格されたコンテキスト (割り込みハンドラーと DPC) だけでなく、任意のプロセスのコンテキストで実行できます。

于 2008-12-14T19:11:08.913 に答える
5

アプリケーションには、事実上連続したバッファーがあります。ご指摘のとおり、この範囲の仮想メモリは、アプリケーションのコンテキストでのみ使用可能であり、その一部はいつでもページアウトされる可能性があります。したがって、デバイスからメモリにアクセスするには(つまり、DMAを実行するには)、メモリをロックダウンし、デバイスに渡すことができる説明を取得する必要があります。

METHOD_IN_DIRECTまたはMETHOD_OUT_DIRECTを使用してIOCTLを(DeviceControl関数を介して)ドライバーに送信することにより、MDLまたはメモリー記述子リストと呼ばれるバッファーの説明を取得できます。IOCTLの定義については、次のページを参照してください。

http://msdn.microsoft.com/en-us/library/ms795909.aspx

デバイスのドライバーにバッファーの説明ができたので、バッファーをロックダウンして、デバイスがバッファーに作用する可能性がある全期間、バッファーがメモリーに残るようにすることができます。MSDNでMmProbeAndLockPagesを検索します。

デバイスは、バッファ内のすべてのメモリを読み書きできる場合とできない場合があります。デバイスは32ビットDMAのみをサポートし、マシンには4GBを超えるRAMが搭載されている場合があります。または、IOMMU、GART、またはその他のアドレス変換テクノロジを備えたマシンを扱っている可能性があります。これに対応するには、さまざまなDMA APIを使用して、デバイスでの使用に適した論理アドレスのセットを取得します。多くの場合、これらの論理アドレスは、質問が最初に尋ねた物理アドレスと同等ですが、常にそうとは限りません。

使用するDMAAPIは、デバイスがスキャッター/ギャザーリストなどを処理できるかどうかによって異なります。ドライバーは、セットアップコードで、IoGetDmaAdapterを呼び出し、ドライバーから返された関数の一部を使用します。

通常、GetScatterGatherListとPutScatterGatherListに関心があります。転送を実行するようにハードウェアを実際にプログラムする関数(ExecutionRoutine)を提供します。

関係する詳細がたくさんあります。幸運を。

于 2009-06-11T00:09:59.333 に答える
5

ユーザー空間からページ テーブルにアクセスすることはできません。それらはカーネルでマップされます。

カーネルを使用している場合は、CR3 の値を調べてベース ページ テーブル アドレスを特定し、解決を開始できます。

このブログシリーズには、これを行う方法のすばらしい説明があります。仮想 <-> 物理アドレスを解決するために、OS 機能/API は必要ありません。

仮想アドレス: f9a10054

1: kd> .formats 0xf9a10054
Binary:  11111001 10100001 00000000 01010100

Page Directory Pointer Index(PDPI)       11                        Index into

1st table(Page Directory Pointer Table) Page Directory Index(PDI)
111001 101 Index into 2nd table(Page Directory Table) Page Table Index(PTI)
00001 0000 Index into 3rd table(Page Table) Byte Index
0000 01010100 0x054, オフセット物理メモリ ページ

彼の例では、windbg を使用しています。!dq は物理メモリの読み取りです。

ここに画像の説明を入力

于 2011-03-18T22:32:21.133 に答える
5

1) いいえ

2) はい、ドライバーを作成する必要があります。仮想ドライバーを使用するか、特別な外部デバイスのドライバーを変更するのが最適です。

3) ここで非常に混乱します。MmGetPhysicalAddress探している方法である必要がありますが、物理アドレスがバンク/チップ/などにどのようにマップされているか本当にわかりません。物理メモリ上。

4) ページ メモリは再配置されるため、使用できません。MmProbeAndLockPagesユーザー モードの呼び出しコンテキストから渡されたメモリに構築できる MDLでページ メモリをロックできます。ただし、非ページ メモリを割り当てて、それをユーザー モード アプリケーションに渡すことをお勧めします。

PVOID p = ExAllocatePoolWithTag( NonPagedPool, POOL_TAG );
PHYSICAL_ADDRESS realAddr = MmGetPhysicalAddress( p );

// use realAddr
于 2008-12-14T16:56:06.033 に答える
4

ユーザーモードでこのようなことをするべきではありませんChristopher が言うように、デバイスがバッキング メモリを使用しているときに mm がバッキング メモリをページアウトすることを決定しないように、ページをロックする必要があります。これにより、ランダムなメモリ ページが破損することになります。

ただし、呼び出しプロセスがドライバーであり、アプリケーションを使用してその関数のドライバーを呼び出している場合、コンテキストを変更していて、mmGetPhysicalAddress ルーチンが呼び出されたときにアプリのコンテキストにいなくなります。

ドライバーには、ユーザー モード アプリのようなコンテキストはありません。IOCTL などを介してドライバーを呼び出している場合、通常は (ただし、保証はされません!) 呼び出し元のユーザー スレッドのコンテキストにいることになります。しかし、実際には、カーネル モード メモリ (0x80000000 を超えるもの) はどこにいても同じマッピングであり、カーネル側でメモリを割り当てることになるため、これはあなたが求めていることには関係ありません。しかし、ここでも、適切な driver を作成してください。WDF ( http://www.microsoft.com/whdc/driver/wdf/default.mspx ) を使用すると、正しいドライバーの作成がはるかに簡単になります (ただし、Windows ドライバーの作成は簡単ではありません)。

編集: 参考になる書籍をいくつか紹介しますが、(ドライバーを書きたくない場合でも) Russinovich と Solomon による Windows Internals ( http://www.amazon.com /Microsoft-Windows-Internals-4th-Server/dp/0735619174/ref=pd_bbs_sr_2?ie=UTF8&s=books&qid=1229284688&sr=8-2 ); Microsoft Windows Driver Model のプログラミングも適切です ( http://www.amazon.com/Programming-Microsoft-Windows-Driver-Second/dp/0735618038/ref=sr_1_1?ie=UTF8&s=books&qid=1229284726&sr=1-1 ) 。

于 2008-12-14T19:28:18.410 に答える
-4

待って、もっとあります。顧客の Vista 64 ビットで実行する特権として、カーネル モード ドライバーを Microsoft に署名させるために、より多くの時間とお金を費やすことができます。

于 2008-12-14T20:28:38.383 に答える