私の C++ プログラム (Windows 上) では、メモリのブロックを割り当てており、物理メモリ内で (つまり、VirtualAllocEx()、MapUserPhysicalPages() などを使用して) ロックされたまま (スワップされておらず、連続している) であることを確認できます。
いいえ、ロックされていることを保証することはできません。プロセスがクラッシュしたり、早期に終了した場合はどうなりますか? ユーザーがそれを殺した場合はどうなりますか?そのメモリは別の用途に再利用され、デバイスがまだ DMA を実行している場合、最終的にデータの損失/破損またはバグチェック (BSOD) が発生します。
また、MapUserPhysicalPages
Windows 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_DIRECT
METHOD_OUT_DIRECT
仮想アドレス空間の連続したページが、物理アドレス空間で連続することはほとんどないことに注意してください。お使いのデバイスがそれを処理できるように設計されていることを願っています。
3. ドライバーを自分で書かなければならない場合、どのように変換すればよいですか? どの機能を使用しますか? mmGetPhysicalAddress()ですか?どうやって使うの?
ドライバーを作成するには、いくつかの API を呼び出すだけではありません。ドライバーを作成する場合は、 MSDNおよびOSRからできるだけ多くの関連資料を読むことをお勧めします。また、Windows Driver Kitの例も参照してください。
4. また、私の理解が正しければ、mmGetPhysicalAddress() は、呼び出しプロセスのコンテキストにある仮想ベース アドレスの物理アドレスを返します。ただし、呼び出しプロセスがドライバーであり、アプリケーションを使用してその関数のドライバーを呼び出している場合、コンテキストを変更していて、mmGetPhysicalAddress ルーチンが呼び出されたときにアプリのコンテキストにいることはなくなります...ドライバーではなく、アプリケーション (ユーザーモード) のメモリ空間で仮想アドレスを変換するにはどうすればよいですか?
ドライバーはプロセスではありません。ドライバーは、さまざまな昇格されたコンテキスト (割り込みハンドラーと DPC) だけでなく、任意のプロセスのコンテキストで実行できます。