Go to main content
Oracle® Solaris 11.3 リンカーとライブラリガイド

印刷ビューの終了

更新: 2015 年 10 月
 
 

プログラムのロード (プロセッサ固有)

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

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

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

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

次の図に、SPARC バージョンの実行可能ファイルの例を示します。

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

image:SPARC 実行ファイルのレイアウト例

次の表に、前の図に示した読み込み可能セグメント要素の定義を示します。

表 43  SPARC: ELF プログラムヘッダーセグメント (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

次の図に、x86 バージョンの実行可能ファイルの例を示します。

図 15  32-bit x86: 実行可能ファイル (64K に整列)

image:x86 実行可能ファイルのレイアウト例。

次の表に、前の図に示した読み込み可能セグメント要素の定義を示します。

表 44  32-bit x86: ELF プログラムヘッダーセグメント (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 ファイルページ (ページサイズとファイルシステムブロックサイズに依存) に、純粋ではないテキストやデータが含まれます。

  • 先頭テキストページには、ELF ヘッダー、プログラムヘッダーテーブル、およびほかの情報が存在します。

  • 最終テキストページには、データの始まりのコピーが存在します。

  • 先頭データページには、テキストの終わりのコピーが存在します。

  • 最後のデータページには、実行中プロセスに関連していないファイル情報が存在できます。論理的にはシステムは、あたかも各セグメントが完全であり分離されているようにメモリーアクセス権を設定します。セグメントのアドレスは調整され、アドレス空間の各論理ページに同じアクセス権セットが確実に存在するようになります。前の例では、テキストの終わりとデータの始まりを保持しているファイル領域が 2 回対応付けされます。 1 回はテキストに関して 1 つの仮想アドレスで対応付けされ、もう 1 回はデータに関して別の仮想アドレスで対応付けされます。


注 - 前の例は、テキストセグメントを丸めた、典型的な Oracle Solaris OS のバイナリを反映したものです。

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

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

図 16  32-bit SPARC: プロセスイメージセグメント

image:SPARC プロセスイメージセグメントの例

図 17  x86: プロセスイメージセグメント

image:x86 プロセスイメージセグメントの例

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

一方、通常は共有オブジェクトのセグメントには、位置独立のコードが存在します。したがって、セグメントの仮想アドレスは、実行動作を無効にすることなくプロセス間で変化させることができます。

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

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

表 45  32-bit SPARC: ELF 共有オブジェクトセグメントアドレスの例
送信元
テキスト
データ
ベースアドレス
ファイル
0x0
0x4000
0x0
プロセス 1
0xc0000000
0xc0024000
0xc0000000
プロセス 2
0xc0010000
0xc0034000
0xc0010000
プロセス 3
0xd0020000
0xd0024000
0xd0020000
プロセス 4
0xd0030000
0xd0034000
0xd0030000
表 46  32-bit x86: ELF 共有オブジェクトセグメントアドレスの例
送信元
テキスト
データ
ベースアドレス
ファイル
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 セグメントからパス名を取り出し、そのインタプリタファイルのセグメントから初期プロセスイメージを作成します。インタプリタはシステムから制御を受け取り、アプリケーションプログラムに対して環境を提供する必要があります。

Oracle Solaris OS では、インタプリタは実行時リンカー ld.so.1(1) として知られています。