10

カーネルとユーザー空間がどのように正確に構造化されているか、メモリのどの部分が占有されているかについて混乱しています。私の現在の(おそらく間違っている)理解は次のとおりです。

  1. プロセスが作成され、このプロセスの仮想メモリがユーザー空間とカーネル空間領域に分割されます。ユーザー空間領域には、プロセスとカーネル空間領域のデータ、コード、スタック、ヒープなどが含まれます。プロセスやカーネル コードのページ テーブルなどが含まれます。カーネルコードがどうなるかはわかりません...ドライバーコードまたは同様のものですか?

  2. また、システム コール テーブルは常にプロセスのカーネル空間の同じ領域にマップされますか? (「プロセスのカーネル空間」と言うのは正しいですか?

  3. 独自のドライバー/モジュールを作成して挿入すると、そのドライバー コードは、作成されるすべての新しいプロセスのカーネル空間に自動的にコピーされますか? そうでない場合...これはどのように機能しますか?

ご意見をお寄せいただきありがとうございます。私の質問を明確にするのに役立つ文献/リンクも問題ありません。

乾杯、ブリック

4

2 に答える 2

32

一般的な考え方はほぼ正しいですが、次の調整を行ってください。マシン全体に対して「カーネル空間」は 1 つしかなく、すべてのプロセスがそれを共有します。

プロセスがアクティブな場合、「ユーザー モード」または「カーネル モード」で実行されている可能性があります。

ユーザー モードでは、CPU によって実行される命令は、メモリ マップのユーザー空間側にあります。プログラムは、独自のコード、またはユーザー空間ライブラリのコードを実行しています。ユーザー モードでは、プロセスの機能は制限されています。CPU には、特権命令の使用を許可しないように指示するフラグがあり、カーネル メモリは、プロセスのメモリ マップに存在しますが、アクセスできません。(どのプログラムにもカーネルのメモリを読み書きさせたくないでしょう。すべてのセキュリティが失われてしまいます。)

プロセスが、たとえばファイルを開くなど、独自の (ユーザー空間) 仮想メモリ内でデータを移動する以外のことをしたい場合、syscall を作成する必要があります。各 CPU アーキテクチャには、syscall を作成する独自の風変わりな方法がありますが、それらはすべて、魔法の命令が実行され、CPU が「特権モード」フラグをオンにし、カーネル空間の特別なアドレス「syscall」にジャンプします。エントリーポイント"。

これで、プロセスはカーネル モードで実行されます。実行中の命令はカーネル メモリに配置され、任意のメモリを読み書きできます。カーネルは、プロセスが行ったばかりの要求を調べて、それをどう処理するかを決定します。

このopen例では、カーネルは の引数に対応する 2 つまたは 3 つのパラメーターを受け取りますint open(const char *filename, int flags[, int mode])。最初の引数は、カーネル空間がユーザー空間へのアクセスを必要とする場合の例を提供します。open("foo", O_RDONLY)文字列"foo"はユーザ​​ー空間のプログラムの一部であるとあなたは言いました。syscall メカニズムは文字列ではなくポインターのみを渡したため、カーネルはユーザー メモリから文字列を読み取る必要があります。

要求されたファイルを見つけるために、カーネルはファイルシステム ドライバー (ファイルの場所を特定するため) を参照し、デバイス ドライバー (必要なブロックをディスクからロードするため) またはネットワーク デバイス ドライバーとプロトコル (リモート ソースからファイルをロードするため) を参照します。 )。これらはすべてカーネルの一部、つまりカーネル空間にあり、組み込みであるかモジュールとしてロードされているかに関係ありません。

リクエストがすぐに満足できない場合、カーネルはプロセスをスリープ状態にすることがあります。これは、ディスクまたはネットワークから応答が受信されるまで、プロセスが CPU から切り離されることを意味します。別のプロセスが実行される可能性があります。その後、応答が返ってくると、プロセスが再び実行を開始します (まだカーネル モードのままです)。ファイルが見つかったので、opensyscall は終了し (パーミッションをチェックし、ファイル記述子を作成します)、ユーザー空間に戻ります。

ユーザー空間に戻るには、CPU を非特権モードに戻し、レジスターをユーザーからカーネルへの移行前の状態に戻すだけです。命令ポインターは、魔法の syscall 命令の後の命令を指します。

syscall 以外にも、ユーザー モードからカーネル モードへの遷移を引き起こす可能性のあるものには、次のものがあります。

  1. ページ フォールト - 物理アドレスが割り当てられていない仮想メモリ アドレスにプロセスがアクセスすると、CPU はカーネル モードに入り、ページ フォールト ハンドラーにジャンプします。次に、カーネルは仮想アドレスが有効かどうかを判断し、物理ページを作成して中断したユーザー空間でプロセスを再開するか、SIGSEGV を送信します。
  2. 割り込み - 一部のハードウェア (ネットワーク、ディスク、シリアル ポートなど) は、注意が必要であることを CPU に通知します。CPU はカーネル モードに入り、ハンドラーにジャンプします。カーネルはそれに応答し、割り込み前に実行されていたユーザー空間プロセスを再開します。

モジュールのロードは、モジュールのコードとデータをカーネル空間にコピーし、その初期化コードをカーネル モードで実行するようにカーネルに要求する syscall で行われます。

かなり長いのでやめておきます。ユーザーとカーネルの遷移に焦点を当てたウォークスルーで、アイデアを固めるのに十分な例が提供されたことを願っています。

于 2013-06-21T03:16:03.643 に答える
3

プロセスの仮想メモリ マップにカーネル空間領域がありません。仮想メモリ マップには、テキスト、bss、データ、ヒープ、ロードされたプログラムのスタック、および共有ライブラリがあります。Linux では、例としてユーザー空間プロセスの /proc/$PID/maps を確認できます。

ユーザー空間プロセスがシステム コールを介して一部のカーネル ドメイン コードにアクセスすると、スタック内のプロセスに代わってカーネル コードが実行されます。明らかに、システム コールから戻った後、すべてのカーネル/ドライバー コードはスタックから削除されます。さらに明確にするために、ある時点でカーネルコードの一部がどのプロセスでも使用されていない場合、それはどのプロセスの仮想メモリマップにも含まれません。

Linux を使用している場合は、Robert Love の「Linux カーネル開発」の本をお勧めします。

于 2013-06-20T20:36:01.480 に答える