7

エミュレートしたいハードウェアがいくつかあります。こんな低レベルでやれるのかな。ハードウェアには多くのレジスタがあり、それらを構造体に配置します。

#include <stdint.h>
struct MyControlStruct
{
    uint32_t data_reg_1;
    uint32_t data_reg_2;
    uint32_t dummy[2]; // to make the following registers have certain addresses
    uint32_t control_reg_1;
    uint32_t control_reg_2;
};
volatile struct MyControlStruct* MyDevice = (struct MyControlStruct*)0xDeadF00;

そのため、Windows と Linux でハードウェア アクセス用に次の構文をサポートしたいと考えています。

MyDevice->data_reg_1 = 42;
MyDevice->data_reg_2 = 100;
MyDevice->control_reg_1 = 1;

コードの最後の行が実行されると、ハードウェア エミュレーターが「起動」して何らかの処理を実行するようにします。これを Windows や Linux に実装できますか? どういうわけか「セグメンテーション違反」信号をキャッチすることを考えましたが、これが Windows で実行できるかどうか、またはまったくできないかどうかはわかりません。

のマニュアルページを見ましたmmap。役立つようですが、どのように使用できるかわかりませんでした。

もちろん、 のような関数を定義することでハードウェアへのアクセスを抽象化することもできWriteToMyDevice、すべてが簡単になります (おそらく) が、この正確な方法でハードウェアへのアクセスを調整できるかどうかを理解したいと思います。

4

3 に答える 3

3

SIGSEGV原則として、不要なページへのアクセスをトラップして処理し、指定されたアドレスがアクセスされていることを確認できるハンドラーを(移植性のない方法で)コーディングできます。

Linuxでこれを行うには、でsigactionシステムコールをSA_SIGINFO使用しucontext_t*、シグナルハンドラーの3番目の引数を使用する必要があります。

これは非常に移植性がありません。Unixごとに(おそらくLinuxカーネルのバージョン番号でさえ問題になる可能性があります)、プロセッサを変更する場合は、コーディングを変える必要があります。

そして、Linuxカーネルはそのような処理があまり速くないと聞いています。

他のより優れたカーネル(Hurd、Plan9)は、ユーザーレベルのページネーションを提供します。

于 2011-10-26T17:05:20.253 に答える
1

実際には、エミュレーターは、純粋なユーザースペースコードを使用してLinux上で(かなり大雑把に)可能です。

エミュレータを構築するには、メモリマップドデバイスをエミュレートしているメモリを監視する2番目のスレッドまたはプロセス(共有メモリ、またはおそらくmmapされたファイルとinotifyを使用)を用意するだけです。

実際のハードウェアドライバーの場合、カーネルコードが少し必要になりますが、それは単に実際のハードウェアアドレスを適切なアクセス許可を持つユーザースペースにマップするものである可能性があります。事実上、これは最新のマルチユーザーオペレーティング環境を古いDOSボックスまたは単純なマイクロコントローラーのように動作するように後退させます-優れた方法ではありませんが、少なくともセキュリティが問題にならない場合は機能します。

検討できるもう1つのことは、仮想マシンでコードを実行することです。

実行するコードが独自のものである場合は、最初に移植可能な方法でコードを記述し、ハードウェアアクセスを抽象化して、プラットフォームごとに再記述できる関数(OS、ハードウェアバージョン、または物理/エミュレート)。これらの手法は、環境を作成する必要がある他の誰かの既存のコードである場合に、より役立ちます。考慮できるもう1つのことは(オリジナルがあまり緊密に統合されていない場合)、特定の関数のダイナミックライブラリレベルのインターセプトを使用することです。たとえば、LinuxのLD_PRELOADやWindowsのラッパーdllを使用します。または、そのことについては、バイナリにパッチを適用します。

于 2011-11-07T14:09:56.283 に答える