リンカーとライブラリ

プログラムの読み込み (プロセッサ固有)

システムは、プロセスイメージを作成または拡張するとき、ファイルのセグメントを仮想メモリーセグメントに論理的にコピーします。システムがファイルをいつ物理的に読み取るかは、プログラムの挙動動やシステムの負荷などに依存します。

プロセスは実行時に論理ページを参照しない限り物理ページを必要とせず、また一般に多くのページを未参照状態のままにします。したがって、物理読み取りを遅延させると、これらの物理読み取りが不要になり、システム性能が向上します。この効率性を実際に実現するには、実行可能オブジェクトファイルと共有オブジェクトファイルには、ファイルオフセットと仮想アドレスがページサイズを法として同じであるセグメントイメージが存在しなければなりません。

32 ビットのセグメントの仮想アドレスとファイルオフセットは、64K (0x10000) を法として同じです。64 ビットのセグメントの仮想アドレスとファイルオフセットは、1 MB (0x100000) を法として同じです。セグメントを最大ページサイズに整列すると、ファイルは物理ページサイズには関係なくページング処理に対して適切になります。

デフォルトでは 64 ビット SPARC プログラムは開始アドレス (0x100000000) にリンクされます。プログラム全体 (テキスト、データ、ヒープ、スタック、共有オブジェクトの依存関係を含む) は、4G バイトより上に存在します。そうすることにより、プログラムがポインタを切り捨てると、アドレス空間の最下位 4G バイトでフォルトが発生することになるので、64 ビットプログラムが正しく作られたことを確認することがより容易になります。64 ビットプログラムは 4G バイトより上でリンクされていますが、コンパイラあるいはリンカーにマップファイルおよび -M オプションを使用することにより、4G バイト未満でリンクすることも可能です (/usr/lib/ld/sparcv9/map.below4G を参照)。

次に SPARC バージョンの例を示します。

図 7-7 SPARC: 実行可能ファイル (64K に整列)

Graphic

表 7-39 SPARC: プログラムヘッダーセグメント(64K に整列)

構成要素 

テキスト 

データ 

p_type

PT_LOAD

PT_LOAD

p_offset

0x0

0x4000

p_vaddr

0x10000

0x24000

p_paddr

指定無し 

指定無し 

p_filesize

0x3a82

0x4f5

p_memsz

0x3a82

0x10a4

p_flags

PF_R + PF_X

PF_R + PF_W + PF_X

p_align

0x10000

0x10000

次に IA バージョンの例を示します。

図 7-8 IA: 実行可能ファイル (64K に整列)

Graphic

表 7-40 IA: プログラムヘッダーセグメント (64K に整列)

構成要素 

テキスト 

データ 

p_type

PT_LOAD

PT_LOAD

p_offset

0x0

0x4000

p_vaddr

0x8050000

0x8064000

p_paddr

指定無し 

指定無し 

p_filesize

0x32fd

0x3a0

p_memsz

0x32fd

0xdc4

p_flags

PF_R + PF_X

PF_R + PF_W + PF_X

p_align

0x10000

0x10000

例で示しているファイルオフセットと仮想アドレスはテキストとデータの両方に対して最大ページサイズを法として同じですが、最大 4 ファイルページ (ページサイズとファイルシステムブロックサイズに依存する) のテキストページまたはデータページは純粋なものではありません (それぞれテキストまたはデータ以外の情報を含みます)。


注 -

上記の例は、テキストセグメントを丸めた、典型的な Solaris のシステムバイナリを反映したものです (表 8-1 を参照)。


データセグメントの終わりは、初期化されていないデータに対して特別な処理を必要とします (初期値が 0 になるようにシステムで定義されている)。したがって、ファイルの最後のデータページに、論理メモリーページに存在しない情報が存在する場合、これらのデータは 0 に設定しなければなりません (実行可能ファイルの未知の内容のままにしてはならない)。

他の 3 ページに存在する純粋でないテキストまたはデータは、論理的にはプロセスイメージの一部ではありません。システムがこれらの純粋でないテキストまたはデータを除去するかどうかについては、規定されていません。このプログラムのメモリーイメージが後に続き、4 キロバイト (0x1000) ページを使用します。単純化するために次の例では、1 ページのサイズのみを示しています。   

図 7-9 SPARC: プロセスイメージセグメント

Graphic

図 7-10 IA: プロセスイメージセグメント

Graphic

セグメント読み込みは、実行可能ファイルと共有オブジェクトでは異なる側面が 1 つ存在します。実行可能ファイルのセグメントには、標準的には絶対コードが存在します。プロセスを正しく実行するには、セグメントは実行可能ファイルを作成するために使用された仮想アドレスに存在しなければなりません。したがって、システムは変化しない p_vaddr 値を仮想アドレスとして使用します。

一方、通常は共有オブジェクトのセグメントには、位置に依存しないコードが存在します。(背景については、第 2 章「リンカー」を参照してください。) したがって、セグメントの仮想アドレスは、実行動作を無効にすることなくプロセスによって異なることができます。

システムは個々のプロセスごとに仮想アドレスを選択しますが、セグメントの相対位置は維持します。位置に依存しないコードはセグメント間で相対アドレス指定を使用するので、メモリーの仮想アドレス間の差は、ファイルの仮想アドレス間の差に一致しなければなりません。

以下の表は、いくつかのプロセスに対する共有オブジェクト仮想アドレスの割り当の例で、一定の相対位置になることを示しています。これらの表は、ベースアドレスの計算も示しています。

表 7-41 SPARC: 共有オブジェクトのセグメントアドレスの例

ソース 

テキスト 

データ 

ベースアドレス 

ファイル 

0x0

0x4000

0x0

プロセス 1 

0xc0000000

0xc0024000

0xc0000000

プロセス 2 

0xc0010000

0xc0034000

0xc0010000

プロセス 3 

0xd0020000

0xd0024000

0xd0020000

プロセス 4 

0xd0030000

0xd0034000

0xd0030000

表 7-42 IA: 共有オブジェクトセグメントアドレスの例

ソース 

テキスト 

データ 

ベースアドレス 

ファイル 

0x0

0x4000

0x0

プロセス 1 

0x8000000

0x8004000

0x80000000

プロセス 2 

0x80081000

0x80085000

0x80081000

プロセス 3 

0x900c0000

0x900c4000

0x900c0000

プロセス 4 

0x900c6000

0x900ca000

0x900c6000

プログラムインタプリタ

動的リンクに関与する実行可能ファイルは、1 つの PT_INTERP プログラムヘッダー要素を持つことができます。exec(2) 時、システムは PT_INTERP セグメントからパス名を取り出し、インタプリタファイルのセグメントから初期プロセスイメージを作成します。つまり、システムは元の実行可能ファイルのセグメントイメージを使用する代わりに、インタプリタのメモリーイメージを作成します。したがって、インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を与えなければなりません。

インタプリタは、次の 2 つの方法のどちらかで制御を受け取ります。方法 1: インタプリタは、実行可能ファイルを読み込むためのファイル記述子 (先頭に位置付けられている) を受け取ることができます。インタプリタは、このファイル記述子を使用して、実行可能ファイルのセグメントをメモリーに読み込んだり対応付けしたりできます。方法 2: 実行可能ファイルの形式によっては、システムはインタプリタにファイル記述子を与える代わりに実行可能ファイルをメモリーに読み込みます。

ファイル記述子が異なる可能性があることを除き、インタプリタの初期プロセス状態は、実行可能ファイルの初期プロセス状態に一致します。インタプリタ自身が、2 番目のインタプリタを必要とすることは許可されません。インタプリタは、共有オブジェクトファイルまたは実行可能ファイルです。