仮想メモリは 2 つの部分に分割されます。伝統的に、0~3GB はユーザースペース用で、3GB~4GB はカーネルスペース用です。
私の質問:
ユーザー空間のスレッドは、カーネル空間のメモリにアクセスできますか?
ARM データシートの場合、アクセス属性はドメイン アクセス制御レジスタを担当します。ただし、カーネル ソース コードでは、ユーザー空間の仮想メモリのページ テーブル エントリのドメイン値は、カーネル空間のページ テーブル エントリと同じです。
仮想メモリは 2 つの部分に分割されます。伝統的に、0~3GB はユーザースペース用で、3GB~4GB はカーネルスペース用です。
私の質問:
ユーザー空間のスレッドは、カーネル空間のメモリにアクセスできますか?
ARM データシートの場合、アクセス属性はドメイン アクセス制御レジスタを担当します。ただし、カーネル ソース コードでは、ユーザー空間の仮想メモリのページ テーブル エントリのドメイン値は、カーネル空間のページ テーブル エントリと同じです。
実際、アプリケーションはページ 0xFFFF0000 にアクセスする可能性があります。ページ 0xFFFF0000 には、swi-handler と他のいくつかのユーザー空間ヘルパーが含まれているためです。いいえ、3/1 分割は魔法のようなものではなく、カーネルが管理するのが非常に簡単なだけです。
通常、カーネルは 3GB を超えるすべてのメモリを、カーネル ドメイン自体のみがアクセスできるようにセットアップします。ドライバーがユーザー空間とカーネル空間の間でメモリを共有する必要がある場合、通常は mmap インターフェースを提供し、エイリアス化されたマッピングを作成するため、同じ物理アドレスに対して 2 つの仮想アドレスができます。これは、VIPT-Cache システムでのみ確実に機能するか、慎重に明示的にキャッシュをフラッシュする場合にのみ機能します。これを望まない場合は、カーネルをハックして、3G スプリットより上のメモリのチャンクをユーザー空間にアクセスできるようにすることができます。ただし、すべてのユーザー空間アプリケーションがこのメモリを共有します。これは、armv5 システムの特別なアプリケーションで 1 回実行しました。
ユーザー空間コードはカーネルメモリを取得していますか? それを許可した唯一のカーネルは、DOS とその昔ながらの仲間でした。質問に戻りますが、次の C コードの例を見てください。
char c=42;
*c=42;
1 バイト (a char
) を取り、それに数値 42 を割り当てます。次に、この非ポインターを逆参照します。これはおそらく仮想メモリの 42 番目のバイトにアクセスしようとしますが、これはほとんど間違いなくあなたのメモリではありません。この例では、カーネル メモリです。これを実行するとどうなるかを推測してください (コンパイラを銃で突き止めた場合):
Segmentation fault
Linux には、最新のオペレーティング システムと同様にメモリ保護機能があります。別のプロセスのメモリにアクセスしようとすると、プロセスは何かを実行する前に終了します (ただし、デバッガーでは他のことがよくわかりません)。そのメモリが別のユーザーランド プロセスのメモリであったとしても、終了してしまいます。root
プログラムが他のプログラムのメモリやカーネルメモリにアクセスできないことはほぼ確実です。カーネルメモリにアクセスする唯一の方法は、カーネルの一部になるか、カーネルの協力を通じて間接的に行うことです。