4

Windows 用に作成されたプログラムは、どのように Windows NT のカーネルと対話したり、コマンドを発行したりするのですか?

また、カーネルはどのようにデータを返しますか?

4

3 に答える 3

1

この質問に答えるには、ユーザー モードとカーネル モードの違いを理解することが重要です。カーネル モードは、実行中のコードがハードウェアに完全にアクセスできる最も特権的な CPU モードです。最も低レベルのオペレーティング システム機能に使用されます。ユーザーモードは、より制限された CPU モードです。コードがハードウェアに直接アクセスするのを防ぎます。アプリケーションはユーザー モードで実行されます。もちろん、何らかの方法でハードウェアにアクセスする必要があるため、カーネルを呼び出す必要があります。

それがあなたの質問につながるところです。ユーザー モード コードがカーネルを呼び出せるようにするために、Windows カーネルはエントリ ポイントを設定します。x86 ベースのシステムでは、このエントリ ポイントはソフトウェア割り込み (int 2e) または sysenter/syscall 命令のいずれかです。これらの命令を実行すると、CPU モードの切り替えが発生し、CPU がユーザー モードからカーネル モードに移行します。CPU がモードを切り替えると、カーネルによって指定された関数が呼び出されます。Windows では、この関数はシステム サービス ディスパッチャです。

システム サービス ディスパッチャーは、ユーザー モード コードが必要とするカーネル サービスの呼び出しを担当します。ユーザー モード コードで指定された関数番号を取得し、システム サービス記述子テーブル (SSDT) で検索します。SSDT は基本的に、各カーネル サービスへの関数ポインターのリストです。正しいカーネル サービスを識別すると、ユーザー モード アプリケーションでも指定された引数を使用してそれを呼び出します。カーネル サービスが完了すると、CPU は、iret 命令 (ソフトウェア割り込みからの場合) または sysexit/sysret (sysenter/syscall からの場合) によってアプリケーションに戻ります。

これらはすべて非常に複雑に聞こえますが、実際にそうであるため、Windows はこれらの詳細をプログラマーから隠しています。カーネルがセットアップするエントリ ポイントを介してカーネルと直接通信する必要がある代わりに、Windows はプログラマーにいくつかの DLL を提供し、プログラマーに代わってこれを行います。

ここで、再びやや複雑になります。ユーザー モードからカーネル サービスを呼び出すプロセスは ntdll.dll に実装されていますが、ほとんどのプログラマは ntdll.dll を直接使用しません。代わりに、ネイティブ API と呼ばれるカーネル サービスの汎用セットをエクスポートします。この上で、Win32 API は kernel32.dll に実装されています。kernel32.dll のほとんどの関数は、ntdll.dll の関数の単なるラッパーです。

なぜこれが行われるのかと尋ねるかもしれません。kernel32.dll にカーネル関数を直接呼び出させないのはなぜですか? この理由は、異なる複数のユーザー モード API を許可するためです。Windows NT は、Win32 だけでなく、POSIX や OS/2 など、複数の API をサポートするように設計されています。各ユーザー モード API は ntdll.dll を呼び出して独自の API を実装し、カーネル サービス自体を直接呼び出す必要がないようにします。

于 2013-11-22T23:31:53.113 に答える
0

これを読んでみてください:第5章-WindowsNT4.0ワークステーションアーキテクチャ。開始するのに十分なはずです。

最終的に、一部のAPIは一部のユーザーランドDLLに直接組み込まれます。これらは直接実行されます。その他には、カーネルモードのヘルプ/サービスが必要です。

これらについて(上記のリンクから引用しています)

アプリケーションはAPIを使用して、ユーザーモードのダイナミックリンクライブラリへのグラフィック呼び出しを行います。呼び出しを実装するコンポーネントは、Executiveに対してカーネルモードトラップ呼び出しを行い、スレッドを切り替えて、呼び出しパラメーターをユーザーモードスタックからカーネルモードスタックにコピーします。次に、プロセッサのスタックレジスタがカーネルモードを指すように切り替えられます。これで、スレッドをExecutiveで実行できます。

アプリケーションは、同じコンピューター上のコンポーネント間の通信のアプリケーションに依存しない方法であるローカルプロシージャコール(LPC)を使用して、保護されたサブシステムと通信します。スレッドがカーネルモードに切り替えられた後、MicrokernelはLPCの配信をスケジュールします。

最適化された通信方法であるFastLPCを使用して、Microkernelは、アプリケーションからの呼び出しに環境サブシステムのスレッドが含まれていることを認識します。呼び出し元のアプリケーションスレッドと受信側のサブシステムスレッドがペアになっていると見なされます。これで、受信スレッドは送信スレッドからの有効期限が切れていない時間を使用できます。

グラフィック呼び出しパラメーターは、受信サブシステム・スレッドに渡されます。受信スレッドは、グラフィックス要求を満たすためにユーザーモードに戻ります。

サブシステムはタスクを完了してから、同じメソッドによってアプリケーション内の待機中の呼び出しスレッドに制御を戻します。

(DLLからの)呼び出し元のスレッドは、アプリケーションに制御を戻す前にユーザーモードに戻されます。

Microsoftオペレーティングシステムのエンジニアは、共有メモリウィンドウの概念を使用して通信を高速化しました。データは、ExecutiveのProcessManagerによって管理される一時的な共有メモリウィンドウに配置されます。これにより、アプリケーションはLPCを使用せずに、サブシステムのメモリを調べてデータを共有できます。ただし、アプリケーションスレッドは引き続きExecutiveで実行する必要があるため、カーネル/ユーザーモードの移行とスレッドの切り替えが引き続き必要です。

ここにexactly、呼び出しがどのように行われるか(使用されるASMコマンドは何ですか)に関するいくつかの注意事項があります。必要に応じて、x86のシステムコールディスパッチャー。

于 2011-09-06T10:35:09.190 に答える
0

おい、それは非常に広い質問です。

これを本当に理解したい場合は、Mark Russinovich et ag による Windows Internalsという本をお勧めします。もう 1 つの優れた本は、Deitel らによる古典的なオペレーティング システムです。

ただし、Helen Custer による Inside Windows NT (第 1 版) から始めてください。これは非常に基本的な本です (最後のリンクには第 2 版の表紙の写真があることに注意してください。これははるかに詳細です)。

一言で言えばわかりました。

Windows コンポーネント間の通信にはさまざまなプロトコルがあります。それらのほとんどは、一日の終わりに共有メモリ(バッファ、スタックなど)を介してデータを渡すことを採用します。しかし、プロトコルは非常に複雑になる可能性があり、通信ごとに異なります。

上記の本を読んで、Windows オペレーティング システムのアーキテクチャがどのように組み合わされているかを判断することをお勧めします。ここから、さまざまなコンポーネントがどのように通信するかがわかります。

(オタク顔を適用) - Windows とオペレーティング システム全般について学習するのに最適な本であると信じてください。

于 2011-09-06T10:29:24.863 に答える