Windows がシステム アドレス空間として 1Gb (または 2Gb) を予約しているのはなぜですか?

StackOverflow https://stackoverflow.com/questions/1115033

質問

Windows アプリケーションには通常、32 ビット システム上で 2 GB のプライベート アドレス空間があることは知られています。このスペースは、/3Gb スイッチを使用して 3Gb まで拡張できます。

オペレーティング システムは、残りの 4Gb を自ら予約します。

私の質問は、なぜですか?

カーネル モードで実行されるコード (つまり、デバイス ドライバー コード) には独自のアドレス空間があります。なぜ、オペレーティング システムは、4 GB の排他的なアドレス空間に加えて、各ユーザー モード プロセスに 2 GB を予約したいのでしょうか?

その理由は、ユーザーモード呼び出しとカーネルモード呼び出しの間の移行にあると思いました。たとえば、次への呼び出し NtWriteFile カーネルディスパッチルーチン用のアドレスが必要になります (そのため、システムは各アプリケーションで 2Gb を予約します)。しかし、使用すると、 SYSENTER, 、システム サービス番号は、カーネル モード コードがどの関数/サービスが呼び出されているかを知るのに十分ではありませんか?

オペレーティング システムが各ユーザー モード プロセスで 2Gb (または 1Gb) を使用することがなぜそれほど重要なのかを説明していただければ幸いです。

役に立ちましたか?

解決

2 つの異なるユーザー プロセスには、異なる仮想アドレス空間があります。仮想アドレスと物理アドレスのマッピングが異なるため、 TLB あるユーザー プロセスから別のユーザー プロセスにコンテキストを切り替えると、キャッシュは無効になります。これは非常にコストがかかります。TLB にアドレスがすでにキャッシュされていないと、メモリ アクセスによって障害が発生し、 PTEs.

Syscall には 2 つのコンテキスト スイッチが含まれます。ユーザー→カーネル、次にカーネル→ユーザー。これを高速化するために、仮想アドレス空間の上位 1GB または 2GB をカーネル用に予約するのが一般的です。仮想アドレス空間はこれらのコンテキスト スイッチ間で変化しないため、TLB フラッシュは必要ありません。これは、各 PTE のユーザー/スーパーバイザー ビットによって有効になり、カーネル メモリがカーネル空間内にある間のみアクセスできるようになります。ページテーブルが同じであっても、ユーザースペースにはアクセスできません。

2 つの別個の TLB に対するハードウェア サポートがあり、1 つはカーネル専用である場合、この最適化は役に立たなくなります。ただし、専用のスペースが十分にある場合は、より大きな TLB を 1 つ作成する方がおそらく価値があります。

x86 上の Linux はかつて「4G/4G スプリット」として知られるモードをサポートしていました。このモードでは、ユーザー空間は 4GB 仮想アドレス空間全体に完全にアクセスでき、カーネルも完全な 4GB 仮想アドレス空間を持ちます。かかる費用は、上でも述べたように、 syscall では、ユーザー メモリとカーネル メモリの間でデータをコピーするためのより複雑なルーチンとともに、TLB フラッシュが必要です。これは、最大 30% のパフォーマンスペナルティを課すことが測定されています。


この質問が最初に尋ねられ、回答されたときから時代は変わりました。64 ビット オペレーティング システムは現在、はるかに普及しています。x86-64 上の現在の OS では、仮想アドレスは 0 から 2 までです。47ユーザー プログラムには -1 (0 ~ 128TB) が許可されますが、カーネルは 2 からの仮想アドレス内に永続的に常駐します。47×(217-1)~264-1 (または -2 から)47 アドレスを符号付き整数として扱う場合は -1 にします)。

32 ビットの実行可能ファイルを 64 ビット Windows で実行するとどうなりますか?すべての仮想アドレスは 0 から 2 であると考えるでしょう。32 (0 ~ 4GB) は簡単に入手できますが、既存のプログラムのバグの露出を避けるために、32 ビット実行可能ファイルは、再コンパイルしない限り、依然として 0 ~ 2GB に制限されています。 /LARGEADDRESSAWARE. 。該当する場合は、0 ~ 4GB にアクセスできます。(これは新しいフラグではありません。同じことが、 /3GB このスイッチにより、デフォルトの 2G/2G ユーザー/カーネル分割が 3G/1G に変更されました。ただし、もちろん 3 ~ 4GB は依然として範囲外です。)

どのような種類のバグがある可能性がありますか?例として、クイックソートを実装していて、2 つのポインターがあるとします。 a そして b 配列の先頭と末尾を過ぎたところを指します。中央をピボットとして選択した場合 (a+b)/2, 、両方のアドレスが 2GB 未満である限り機能しますが、両方とも 2GB を超えると、加算で整数のオーバーフローが発生し、結果が配列の外になります。(正しい表現は a+(b-a)/2.)

余談ですが、デフォルトの 3G/1G ユーザー/カーネル分割を備えた 32 ビット Linux では、これまでスタックが 2 ~ 3GB の範囲にあるプログラムを実行してきたため、そのようなプログラミング エラーはおそらくすぐにフラッシュされるでしょう。64 ビット Linux では、32 ビット プログラムが 0 ~ 4 GB にアクセスできます。

他のヒント

のWindows(任意のOS等)は、カーネル+ドライバーよりも多くある。

あなたのアプリケーションは、単にカーネル空間に存在しないOSサービスの多くに依存しています。 バッファ、ハンドルとあなたのプロセス自身のアドレス空間にマッピングされ得ることができ、リソースのすべての種類がたくさんあります。あなたは、たとえば、ウィンドウハンドル、またはブラシを返すのWin32 API関数を呼び出すたびに、これらのものは、あなたのプロセスのどこかに割り当てられる必要があります。ように、Windowsの一部は、カーネル内で実行さ、はい、他の部分は、独自のユーザーモードプロセスで実行され、いくつかは、もののアプリケーションは、あなたのアドレス空間にマッピングされ、への直接アクセスを必要とします。これの一部は避けることは難しいですが、重要な追加要因は、パフォーマンスです。 のすべてののWin32のコールは、コンテキスト・スイッチを必要とする場合は、主要なパフォーマンスヒットになります。彼らが依存するデータが既にあなたのアドレス空間にマッピングされているので、それらのいくつかは、ユーザーモードで処理することができた場合は、コンテキストスイッチが回避され、あなたはかなりの数のCPUサイクルを保存します。

だから、任意のOSのニーズはを脇に設定されたアドレス空間の一部の量。 私は、OSのデフォルトのセットのみ1ギガバイトでのLinuxを信じています。

Windowsがかつてレイモンド陳氏のブログで説明したとMSが2GBに落ち着いた理由。私はリンクを持っていない、と私は詳細を覚えていないことができますが、Windows NTは、もともとだけでなくAlphaプロセッサをターゲットにしたため、決定がなされた、とAlphaの上、50/50を行うにはいくつかの本当に良い理由がありましたスプリット。 ;)

アルファの32のサポートだけでなく、64ビットコードとは何かでした。 :)

  カーネルモード(すなわち、デバイス・ドライバ・コード)で実行されている

コードは、それ自身のアドレス空間を持ちます。

はありませんそれはしていません。これは、x86プロセッサ上のプロセスのユーザモード部が、そのアドレス空間を共有しなければなりません。カーネルは合計で十分なスペースを確保し、アドレス空間を有限する必要がある理由です。

一部の答えはないの歴史をマイクロプロセッサ述べた。こちらは一部の私が知り、その他を提供できる最近の。

インテル8086のプロセッサのたセグメント-オフセット建築のためのメモリ、20ビットメモリアドレス、そのための総抗体のメモリ1MB.

とは異なり競争プロセッサの時代のようにZilog Z80-インテル8086のた アドレス空間 った様な電子メモリがすべて入力/出力通信などのマイナ周辺機器としてキーボード、シリアルポート、プリンタポートやビデオ表示されます。(比較のためのZilog Z80たのは、入力/出力アドレスを専用の組み立てopcodesのアクセス)

する必要性につスペースが増え続けている範囲の周辺の拡大を決めセグメントのアドレス空間の電子メモリから0-640K、"その他のもの"(入力/出力、ROM、ビデオメモリなど)から640Kに1MB.

としてのx86ラインの拡大と進化して、Pcに進化し、同様のスキームを使用していますが、終試2G/2G分割の4Gアドレス空間です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top