システムは、プロセスイメージを作成または拡張するとき、ファイルのセグメントを仮想メモリーセグメントに論理的にコピーします。システムがファイルをいつ物理的に読み取るかは、プログラムの挙動動やシステムの負荷などに依存します。
プロセスは実行時に論理ページを参照しない限り物理ページを必要とせず、また一般に多くのページを未参照状態のままにします。したがって、物理読み取りを遅延させると、これらの物理読み取りが不要になり、システム性能が向上します。この効率性を実際に実現するには、実行可能オブジェクトファイルと共有オブジェクトファイルには、ファイルオフセットと仮想アドレスがページサイズを法として同じであるセグメントイメージが存在しなければなりません。
32ビットのセグメントの仮想アドレスとファイルオフセットは、64K (0x10000) を法として同じです。64 ビットのセグメントの仮想アドレスとファイルオフセットは、1 MB (0x100000) を法として同じです。セグメントを最大ページサイズに整列すると、ファイルは物理ページサイズには関係なくページング処理に対して適切になります。
デフォルトでは 64 ビット SPARC プログラムは開始アドレス (0x100000000) にリンクされます。プログラム全体 (テキスト、データ、ヒープ、スタック、共有オブジェクトの依存関係を含む) は、4G バイトより上に存在します。そうすることにより、プログラムがポインタを切り捨てると、アドレス空間の最下位 4G バイトでフォルトが発生することになるので、64 ビットプログラムが正しく作られたことを確認することがより容易になります。64 ビットプログラムは 4G バイトより上でリンクされていますが、リンカーマップファイルとコンパイラあるいはリンカーに -M オプションを付けて使用することにより、4G バイトより下でリンクすることも可能です (/usr/lib/ld/sparcv9/map.below4G を参照)。
次に SPARC バージョンの例を示します。
構成要素 |
テキスト |
データ |
---|---|---|
p_type |
PT_LOAD |
PT_LOAD |
p_offset |
0x100 |
0x2bf00 |
p_vaddr |
0x10100 |
0x4bf00 |
p_paddr |
指定なし |
指定なし |
p_filesize |
0x2be00 |
0x4e00 |
p_memsz |
0x2be00 |
0x5e24 |
p_flags |
PF_R+PF_X |
PF_R+PF_W+PF_X |
p_align |
0x10000 |
0x10000 |
次に IA バージョンの例を示します。
構成要素 |
テキスト |
データ |
---|---|---|
p_type |
PT_LOAD |
PT_LOAD |
p_offset |
0x100 |
0x2bf00 |
p_vaddr |
0x8048100 |
0x8074f00 |
p_paddr |
指定なし |
指定なし |
p_filesize |
0x2be00 |
0x4e00 |
p_memsz |
0x2be00 |
0x5e24 |
p_flags |
PF_R + PF_X |
PF_R + PF_W + PF_X |
p_align |
0x1000 |
0x1000 |
例で示しているファイルオフセットと仮想アドレスはテキストとデータの両方に対して最大ページサイズを法として同じですが、最大 4 ファイルページ (ページサイズとファイルシステムブロックサイズに依存する) のテキストページまたはデータページは純粋なものではありません (それぞれテキストまたはデータ以外の情報を含みます)。
先頭テキストページには、ELF ヘッダー、プログラムヘッダーテーブル、および他の情報が存在する
最終テキストページには、データの始まりのコピーが存在する
先頭データページには、テキストの終わりのコピーが存在する
最後のデータページには、実行中プロセスに関連していないファイル情報が存在できる。論理的にはシステムは、あたかも各セグメントが完全であり分離されているようにメモリーアクセス権を設定する。セグメントのアドレスは、アドレス空間の各論理ページに同じ許可が確実に存在できるよう調整される。上の例では、テキストの終わりとデータの始まりを保持しているファイル領域が 2 回対応付けされます (1 回はテキストに関して 1 つの仮想アドレスで対応付けされ、もう 1 回はデータに関して別の仮想アドレスで対応付けされる)
データセグメントの終わりは、初期化されていないデータに対して特別な処理を必要とします (初期値が 0 になるようにシステムで定義されている)。したがって、ファイルの最後のデータページに、論理メモリーページに存在しない情報が存在する場合、これらのデータは 0 に設定しなければなりません (実行可能ファイルの未知の内容のままにしてはならない)。
他の 3 ページに存在する純粋でないテキストまたはデータは、論理的にはプロセスイメージの一部ではありません。システムがこれらの純粋でないテキストまたはデータを除去するかどうかについては、規定されていません。このプログラムのメモリーイメージが後に続き、4 キロバイト (0x1000) ページを使用します。単純化するために次の例では、1 ページのサイズのみを示しています。
セグメント読み込みは、実行可能ファイルと共有オブジェクトでは異なる側面が 1 つ存在します。実行可能ファイルのセグメントには、標準的には絶対コードが存在します。プロセスを正しく実行するには、セグメントは実行可能ファイルを作成するために使用された仮想アドレスに存在しなければなりません。したがって、システムは変化しない p_vaddr 値を仮想アドレスとして使用します。
一方、通常は共有オブジェクトのセグメントには、位置に依存しないコードが存在します。(背景については、第 2 章「リンカー」を参照してください。) したがって、セグメントの仮想アドレスは、実行動作を無効にすることなくプロセスによって異なることができます。
システムは個々のプロセスごとに仮想アドレスを選択しますが、セグメントの相対位置は維持します。位置に依存しないコードはセグメント間で相対アドレス指定を使用するので、メモリーの仮想アドレス間の差は、ファイルの仮想アドレス間の差に一致しなければなりません。
以下の表は、いくつかのプロセスに対する共有オブジェクト仮想アドレスの割り当の例で、一定の相対位置になることを示しています。これらの表は、基底アドレスの計算も示しています。
表 7-39 SPARC: 共有オブジェクトセグメントアドレスの例
ソース |
テキスト |
データ |
基底アドレス |
---|---|---|---|
ファイル |
0x200 |
0x2a400 |
0x0 |
プロセス 1 |
0xc0000200 |
0xc002a400 |
0xc0000000 |
プロセス 2 |
0xc0010200 |
0xc003c400 |
0xc0010000 |
プロセス 3 |
0xd0020200 |
0xd004a400 |
0xd0020000 |
プロセス 4 |
0xd0030200 |
0xd005a400 |
0xd0030000 |
表 7-40 IA: 共有オブジェクトセグメントアドレスの例
ソース |
テキスト |
データ |
基底アドレス |
---|---|---|---|
ファイル |
0x200 |
0x2a400 |
0x0 |
プロセス 1 |
0x80000200 |
0x8002a400 |
0x80000000 |
プロセス 2 |
0x80081200 |
0x800ab400 |
0x80081000 |
プロセス 3 |
0x900c0200 |
0x900ea400 |
0x900c0000 |
プロセス 4 |
0x900c6200 |
0x900f0400 |
0x900c6000 |
実行可能ファイルには、1 つの PT_INTERP プログラムヘッダー要素が存在できます。exec(2) 時、システムは PT_INTERP セグメントからパス名を取り出し、インタプリタファイルのセグメントから初期プロセスイメージを作成します。つまり、システムは元の実行可能ファイルのセグメントイメージを使用する代わりに、インタプリタのメモリーイメージを作成します。したがって、インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を与えなければなりません。
インタプリタは、次の 2 つの方法のどちらかで制御を受け取ります。方法 1: インタプリタは、実行可能ファイルを読み込むためのファイル記述子 (先頭に位置付けられている) を受け取ることができます。インタプリタは、このファイル記述子を使用して、実行可能ファイルのセグメントをメモリーに読み込んだり対応付けしたりできます。方法 2: 実行可能ファイルの形式によっては、システムはインタプリタにファイル記述子を与える代わりに実行可能ファイルをメモリーに読み込みます。
ファイル記述子が異なる可能性があることを除き、インタプリタの初期プロセス状態は、実行可能ファイルの初期プロセス状態に一致します。インタプリタ自身が、2 番目のインタプリタを必要とすることは許されません。インタプリタは、共有オブジェクトファイルまたは実行可能ファイルです。
共有オブジェクト (一般的な場合) は位置に依存しないものとして読み込みされ、アドレスはプロセスによって異なる。システムは、mmap(2) および関連するサービスで使用される動的セグメント領域にセグメントを作成する。したがって、一般的に、共有オブジェクトインタプリタは元の実行可能ファイルの元のセグメントアドレスと競合しない