Linuxカーネルについて学んでいますが、Linuxでユーザーモードからカーネルモードに切り替える方法がわかりません。それはどのように機能しますか?アドバイスをいただけますか、それを参照するためのリンクやこれに関する本を教えてください。
3 に答える
ユーザースペースアプリケーションが通常の操作中にカーネルモードへの切り替えを明示的に開始できる唯一の方法は、open、read、writeなどのシステムコールを行うことです。
ユーザーアプリケーションが適切なパラメーターを使用してこれらのシステムコールAPIを呼び出すたびに、ソフトウェア割り込み/例外(SWI)がトリガーされます。
このSWIの結果として、コード実行の制御は、ユーザーアプリケーションから、OSによって提供される割り込みベクトルテーブル[IVT]内の事前定義された場所にジャンプします。
このIVTには、SWI例外ハンドラルーチンのアドレスが含まれています。このルーチンは、ユーザーアプリケーションをカーネルモードに切り替え、ユーザープロセスに代わってカーネル命令の実行を開始するために必要なすべての手順を実行します。
ユーザーモードからカーネルモードに切り替えるには、システムコールを実行する必要があります。
内部で何が起こっているのかを知りたいだけの場合は、TLDPにアクセスして新しい友達になり、コードを確認してください(十分に文書化されており、アセンブリコードを理解するための追加の知識は必要ありません)。
に興味があります:
movl $len,%edx # third argument: message length
movl $msg,%ecx # second argument: pointer to message to write
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel
ご覧のとおり、システムコールはアセンブリコードの単なるラッパーであり、割り込み(0x80)を実行し、その結果、このシステムコールのハンドラーが呼び出されます。
少しごまかして、ここでCプリプロセッサを使用して実行可能ファイルを作成しましょう(foo.Sは、以下のリンクからコードを配置するファイルです)。
gcc -o foo -nostdlib foo.S
straceを介して実行し、記述した内容を確実に取得します。
$ strace -t ./foo
09:38:28 execve("./foo", ["./foo"], 0x7ffeb5b771d8 /* 57 vars */) = 0
09:38:28 stat(NULL, Hello, world!
NULL) = 14
09:38:28 write(0, NULL, 14)
これを読んだだけで、かなり良いリソースです。ユーザーモードとカーネルモード、変更が発生する理由、変更の費用について説明し、興味深い関連資料を提供します。
http://www.codinghorror.com/blog/2008/01/understanding-user-and-kernel-mode.html
ここに短い抜粋があります:
カーネルモード
カーネルモードでは、実行中のコードは、基盤となるハードウェアに完全かつ無制限にアクセスできます。任意のCPU命令を実行し、任意のメモリアドレスを参照できます。カーネルモードは通常、オペレーティングシステムの最低レベルで最も信頼できる機能のために予約されています。カーネルモードでのクラッシュは壊滅的です。PC全体を停止します。
ユーザーモード
ユーザーモードでは、実行中のコードはハードウェアまたは参照メモリに直接アクセスすることはできません。ユーザーモードで実行されているコードは、ハードウェアまたはメモリにアクセスするためにシステムAPIに委任する必要があります。この種の分離によって提供される保護により、ユーザーモードでのクラッシュは常に回復可能です。コンピューターで実行されているコードのほとんどは、ユーザーモードで実行されます。