グローバル記述子テーブル( GDT ) は、 80286以降のIntel x86ファミリ プロセッサで使用されるデータ構造であり、プログラム実行中に使用されるさまざまなメモリ領域の特性 (ベース アドレス、サイズ、実行可能性や書き込み可能性などのアクセス権限を含む) を定義します。これらのメモリ領域は、 Intel 用語ではセグメントと呼ばれます。
説明
GDT は 8 バイトのエントリのテーブルです。各エントリは、セグメント記述子、タスク状態セグメント(TSS)、ローカル記述子テーブル(LDT)、またはコール ゲートを参照します。コール ゲートは x86 特権レベル間で制御を転送するために設計されましたが、このメカニズムはほとんどの最新のオペレーティング システムでは使用されていません。
ローカル記述子テーブル (LDT) もあります。GDT では複数の LDT を定義できますが、一度に現在有効なのは 1 つだけです。通常、現在のタスクに関連付けられています。LDT には特定のプロセス専用のメモリ セグメントが含まれますが、GDT にはグローバル セグメントが含まれます。x86 プロセッサには、特定のマシン イベントで現在の LDT を自動的に切り替える機能がありますが、GDT を自動的に切り替える機能はありません。
プロセスによって実行されるすべてのメモリ アクセスは、常にセグメントを経由します。80386 プロセッサ以降では、 32ビットのセグメント オフセットと制限により、セグメントがアドレス指定可能なメモリ全体をカバーできるようになり、セグメント相対アドレス指定がユーザーにとって透過的になります。
セグメントを参照するには、プログラムは GDT または LDT 内のインデックスを使用する必要があります。このようなインデックスは、セグメント セレクタ(またはセレクタ) と呼ばれます。セレクタは、使用するセグメント レジスタにロードする必要があります。メモリ内の GDT および割り込み記述子テーブル(IDT)の位置を設定/取得できるマシン命令とは別に、メモリを参照するすべてのマシン命令には暗黙のセグメント レジスタがあり、場合によっては 2 つあります。ほとんどの場合、このセグメント レジスタは、命令の前にセグメント プレフィックスを追加することでオーバーライドできます。
セレクターをセグメント レジスタにロードすると、ロード時に GDT または LDT エントリが読み取られ、セグメントのプロパティが非表示のレジスタにキャッシュされます。その後の GDT または LDT への変更は、セグメント レジスタが再ロードされるまで有効になりません。

64 ビットの GDT
GDT は 64 ビット モードでも存在します。GDT を定義する必要がありますが、通常は変更されたり、セグメント化に使用されたりすることはありません。レジスタのサイズは 48 ビットから 80 ビットに拡張され、64 ビット記述子は常に「フラット」です (つまり、0x00000000000000000 から 0xFFFFFFFFFFFFFFFFFF まで)。ただし、FS と GS のベースは 0 に制限されず、プロセス環境ブロックやスレッド情報ブロックなどの項目のオフセットへのポインターとして引き続き使用されます。
システム ビット (アクセス フィールドの 4 番目のビット) がクリアされている場合、記述子のサイズは 8 バイトではなく 16 バイトになります。これは、コード/データ セグメントは無視されますが、TSS は無視されませんが、TSS ポインターは 64 ビット長になる可能性があり、そのため記述子には TSS ポインターの上位 dword を挿入するためのスペースがさらに必要になるためです。
64ビット版のWindowsではGDTのフックが禁止されており、フックしようとするとマシンでバグチェックが発生します。[1]
ローカル記述子テーブル
ローカル記述子テーブル( LDT ) は、 x86 アーキテクチャで保護モードで使用されるメモリ テーブルであり、GDT と同様に、線形メモリ内のアドレス開始、サイズ、実行可能性、書き込み可能性、アクセス権限、メモリ内での実際の存在などのメモリ セグメント記述子 が含まれています。
LDT はグローバル記述子テーブル (GDT) の兄弟であり、それぞれがプログラムからアクセス可能な最大 8192 個のメモリ セグメントを定義します。GDT とは異なり、0 番目のエントリは有効なエントリであり、他の LDT エントリと同様に使用できることに注意してください。また、GDT とは異なり、LDT は特定のシステム エントリ ( TSSまたは LDT) の保存に使用できないことにも注意してください。ただし、コール ゲートとタスク ゲートは問題ありません。
歴史
Intel 80286のようなページング機能を持たない x86 プロセッサでは、複数のプロセスに別々のアドレス空間を実装するために LDT が不可欠です。通常、ユーザー プロセスごとに 1 つの LDT があり、プライベートに保持されているメモリを記述しますが、共有メモリとカーネルメモリは GDT によって記述されます。オペレーティング システムは、新しいプロセスをスケジュールするとき、LLDT マシン命令を使用するか、 TSS を使用するときに、現在の LDT を切り替えます。逆に、GDT は通常は切り替えられません (ただし、VMwareなどの仮想マシン モニターがコンピューター上で実行されている場合は、切り替えられる可能性があります)。
両方のテーブル間の対称性の欠如は、現在の LDT が特定のイベントで自動的に切り替えられるという事実、特にTSSベースのマルチタスクが使用されている場合にそれが可能であるのに対し、GDT ではそれが不可能であるという事実によって強調されています。また、LDT は特定の特権タイプのメモリ セグメント (TSS など) を保存できません。最後に、LDT は実際には GDT 内の記述子によって定義されますが、GDT は線形アドレスによって直接定義されます。
GDT を介して共有メモリを作成すると、いくつかの欠点があります。特に、このようなメモリはすべてのプロセスから参照可能であり、権限も同等です。共有メモリの可視性を制限し、共有メモリの保護を差別化するには、たとえば一部のプロセスに読み取り専用アクセスのみを許可するなど、同じ物理メモリ領域を指し、特定の共有メモリ領域へのアクセスを要求したプロセスの LDT にのみ作成される個別の LDT エントリを使用できます。
同一のメモリ領域を指す LDT (および GDT) エントリは、エイリアスと呼ばれます。エイリアスは通常、コード セグメントへの書き込みアクセスを取得するためにも作成されます。実行可能セレクターは書き込みには使用できません。(すべてが同じメモリ セグメントに配置される、いわゆる小さな メモリ モデルで構築された保護モードプログラムは、コードとデータ/スタックに別々のセレクターを使用する必要があり、両方のセレクターは技術的には「エイリアス」になります。) GDT の場合、エイリアスは TSS などのシステム セグメントにアクセスするためにも作成されます。
セグメントの記述子には「存在」フラグがあり、必要に応じてメモリから削除できます。たとえば、コード セグメントまたは変更されていないデータ セグメントは破棄でき、変更されたデータ セグメントはディスクにスワップ アウトできます。ただし、セグメント全体を 1 つの単位として操作する必要があるため、スワップがタイムリーに行われるように、セグメントのサイズを制限する必要があります。ただし、より小さく、簡単にスワップできるセグメントを使用すると、セグメント レジスタをより頻繁に再ロードする必要があり、それ自体が時間のかかる操作になります。
現代の用法
Intel 80386マイクロプロセッサはページングを導入しました。これは、同じ仮想アドレスに個別の物理メモリ ページ (それ自体が非常に小さなメモリ ユニット) を割り当てるもので、ディスク ページングはセグメント スワッピングよりもはるかに高速で効率的であるという利点があります。そのため、最新の 32 ビット x86 オペレーティング システムでは、主に従来の16 ビットコードを実行するために LDT がほとんど使用されません。
16 ビット コードを 32 ビット環境でメモリを共有しながら実行する必要がある場合 (たとえば、OS/2 1.x プログラムを OS/2 2.0 以降で実行する場合など)、LDT は、すべてのフラット(ページ化) アドレスが LDT 内にセレクターを持つように記述する必要があります(通常、これにより LDT は 64 KiB エントリで埋められます)。この手法は、LDT タイリングと呼ばれることもあります。LDT のサイズが制限されているため、仮想フラット アドレス空間は 512 メガバイト (8191 x 64 KiB) に制限される必要があります。これは OS/2 で発生している現象ですが、この制限はバージョン 4.5 で修正されました。また、32 ビット環境で割り当てられたオブジェクトが 64 KiB 境界を越えないようにする必要があります。越えると、アドレス空間の無駄が発生します。
32 ビット コードが任意のメモリ オブジェクトを 16 ビット コードに渡す必要がない場合 (たとえば、Windows NTに存在する OS/2 1.x エミュレーションや Windows 3.1エミュレーション レイヤーなど)、32 ビット アドレス空間のサイズを人為的に制限する必要はありません。
参考文献
- ^ 「x64 ベース システムのパッチ適用ポリシー」。2009 年 10 月 8 日。2022 年 1 月 19 日時点のオリジナルよりアーカイブ。2020年12 月 11 日に閲覧。
オペレーティング システムがこれらの変更またはその他の不正なパッチを検出すると、バグ チェックを生成し、システムをシャットダウンします。
外部リンク
- Intel アーキテクチャ ソフトウェア開発者マニュアル
- GDT テーブルは、OSDev.org のWayback Machineに 2009-10-17 にアーカイブされています。
- GDT チュートリアルは、OSDev.org のWayback Machineに 2009-02-14 にアーカイブされています。
- Bran のカーネル開発 GDT チュートリアルは、2008 年 2 月 3 日にWayback Machineにアーカイブされました。
- BrokenThorn 保護モード 2018-04-23 にWayback Machineでアーカイブされました
