インタビューでこんな質問をされました。
Windows で、いくつかの dll に依存する exe があるとします。exe を起動すると、依存する dll が読み込まれます。これらの dll は、カーネル モードまたはユーザー モードで読み込まれますか?
答えに言及するのではなく、質問についてよくわかりません-説明を手伝ってもらえますか?
ありがとう。
インタビューでこんな質問をされました。
Windows で、いくつかの dll に依存する exe があるとします。exe を起動すると、依存する dll が読み込まれます。これらの dll は、カーネル モードまたはユーザー モードで読み込まれますか?
答えに言及するのではなく、質問についてよくわかりません-説明を手伝ってもらえますか?
ありがとう。
私は Windows が内部でどのように機能するかについての専門家ではありませんが、私が知っている限りでは、正しい答えはユーザー モードです。なぜなら、オペレーティング システムに関連するプロセスだけがカーネル スペースで許可されているからですhttp://en.wikibooks.org/ wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
基本的にOSのプロセスでなければ、ユーザー空間に配置されます。
質問は非常に不正確/あいまいです。「Windows で」は何かを示唆していますが、明確ではありません。おそらく、インタビュアーは Win32 サブシステム、つまりエンド ユーザーとして通常目にする Windows の一部について言及していたようです。質問の最後の部分はさらにあいまいです。
プロセス オブジェクトとセクション オブジェクト (MSDN では MMF と呼ばれる、 および などのロードされた PE イメージ.exe
).dll
は.sys
実際にはカーネルオブジェクトであり、基になるエグゼクティブ (およびメモリ マネージャーなど) からの支援が必要ですが、DLL 内のそれぞれのコード ( ) は、ユーザー モード プロセスから呼び出された場合DllMain
、他のユーザー モード プロセスとまったく同じように動作します。つまり、DLL からコードを実行している各スレッドは、カーネル モードに移行して、最終的に OS サービスを利用する (ファイルを開く、PE ファイルをロードする、イベントを作成するなど) か、それで十分な場合はいつでもユーザー モードで何かを実行します。
おそらく、インタビュアーは、伝統的に 32 ビットの 2 GB 境界にある、「カーネル空間」や「ユーザー空間」と呼ばれることもあるメモリ範囲にも関心を持っていたのでしょう。はい、通常、DLL は 2 GB 境界より下、つまり「ユーザー空間」で終了しますが、他の共有メモリ (メモリ マップ ファイル、MMF) は通常、その境界より上で終了します。
インタビュアーが DLL に関する一般的な誤解の犠牲になった可能性さえあります。DLL 自体はメモリの休眠部分に過ぎず、単独で実行されることはありません(そうです、これは にも当てはまりますDllMain
)。確かに、ローダーは再配置などのあらゆる種類のことを処理しますが、最終的には、明示的または暗黙的に呼び出されない限り何も実行されません (DLL をロードするプロセスのスレッドのコンテキストで)。したがって、すべての実用的な目的のために、質問はあなたに尋ねる必要があります.
インタビュアーは、彼/彼が尋ねている概念について明確な考えを持っているかどうか疑問に思う.
もう少し情報を追加させてください。他の回答へのコメントから、人々はDLLについてもドライバーについても同じ誤解をしているようです。ドライバーは、EXE (または最終的には「プロセス」) の概念よりも DLL の概念にはるかに近いものです。問題は、ほとんどの場合、ドライバーはそれ自体で何もしないということです(ただし、システム スレッドを作成して変更することはできます)。ドライバーはプロセスではなく、プロセスを作成しません。
その答えは、Windows 向けの何らかの重要なアプリケーション開発を行っている人にとっては、明らかにユーザー モードです。2つのことを説明しましょう。
DLL
ダイナミック リンク ライブラリは、通常の古いリンク ライブラリまたは .lib とよく似ています。アプリケーションで .lib を使用すると、コンパイル直後に関数定義が貼り付けられます。通常、.lib を使用して API を保存し、プロジェクト全体を再構築することなく関数を変更します。インターフェイス (関数名とパラメーター) が変更されていない限り、同じ名前の新しい .lib を古いものの上に貼り付けるだけです。それはまだ動作します。優れたモジュール性。
.dll はまったく同じことを行いますが、再リンクやコンパイルは必要ありません。.dll は、本質的に、それを使用するアプリケーションと同じように .exe にコンパイルされる .lib と考えることができます。名前と関数の署名を共有する新しい .dll を配置するだけで、すべてが機能します。.dll を置き換えるだけで、アプリケーションを更新できます。これが、ほとんどの Windows ソフトウェアが .dll といくつかの exe で構成されている理由です。
.dll の使用は 2 つの方法で行われます
暗黙のリンク
.dll がある場合にこの方法でリンクするには、dll のすべてのエントリ ポイントを定義するuserapplication.dll
があります。userapplication.lib
静的リンク ライブラリにリンクし、作業ディレクトリに .dll を含めるだけです。
明示的なリンク
LoadLibrary(userapplication.dll)
または、.dllへのハンドルを返す を最初に呼び出して、プログラムで .dll をロードすることもできます。次にGetProcAddress(handle, "FunctionInUserApplicationDll")
、使用できる関数ポインターを返します。このようにして、アプリケーションはそれを使用する前にチェックすることができます。c#
少し違いますが簡単です。
ユーザー/カーネルモード
Windows には、2 つの主要な実行モードがあります。ユーザー モードとカーネル モード (カーネルはさらにシステムとセッションに分割されます)。ユーザー モードの場合、物理メモリ アドレスは不透明です。ユーザーモードは、実メモリ空間にマッピングされた仮想メモリを利用します。ユーザー モード ドライバーも偶然にも .dll です。ユーザー モード アプリケーションは通常、約 4Gb の仮想アドレス空間を使用して動作します。2 つの異なるアプリケーションは、そのアプリケーションまたはプロセスのコンテキスト内にあるため、それらのアドレスを意味のある形で使用することはできません。ユーザー モード アプリケーションが、カーネル モード ドライバーにフォールバックしない限り、物理メモリ アドレスであることを知る方法はありません。基本的に、プログラミングに慣れているすべてのもの (ドライバーを開発しない限り)。
カーネル モードは、ユーザー モード アプリケーションから保護されています。ほとんどのハードウェア ドライバーはカーネル モードのコンテキストで動作し、通常、すべての Windows API はユーザーとカーネルの 2 つのカテゴリに分類されます。カーネル モード ドライバーはカーネル モード API を使用し、ユーザー モード API を使用しないため、ユーザー .dll を使用しません (ユーザー モード API セットであるコンソールに出力することさえできません)。代わりに、ドライバーである .sys ファイルを使用し、基本的にユーザー モードでまったく同じように動作します。.sys は pe 形式であるため、基本的に .exe は .dll と同じように、main() エントリ ポイントのない .exe に似ています。
質問者の観点からすると、2 つのグループがあります。
[kernel/.sys] および [user/.dll または .exe]
オペレーティング システムがユーザーではなくすべてを実行するため、実際にはカーネルに .exe はありません。システムまたは別のカーネルコンポーネントが何かを開始するとき、DriverEntry() メソッドを呼び出すことでそれを行うので、それは main() のようなものだと思います。
したがって、この意味でのこの質問は非常に簡単です。