リンカーとライブラリ

初期設定および終了ルーチン

制御をアプリケーションに転送する前に、実行時リンカーは、アプリケーションの依存関係内で検出された初期設定 (.init) および終了 (.fini) セクションを処理します。これらのセクションとこれを説明するシンボルは、その依存関係のリンク編集中に作成されます (「セクションの初期設定と終了」を参照)。

Solaris 2.5.1 以前のリリースでは、依存関係からの初期設定ルーチンは、読み込まれた順序の降順で、つまり、ldd(1) を使用して表示された依存関係と逆の順序で呼び出されていました。

Solaris 2.6 リリースからは、実行時リンカーは、読み込まれた依存関係から、初期設定ルーチンの依存関係の配列リストを作成します。このリストは、各オブジェクトが表す依存関係の相関関係に加えて、表示された依存関係の外部で発生した結合から構成されます。

.init セクションは、依存関係が配列された順序の逆の順序で実行されます。周期性のある依存関係が検出された場合は、その周期を形成するオブジェクトは、トポロジカルソートは実行できません。そのため、この .init セクションは、読み込まれた順序で実行されることになります。

-i オプションを指定した ldd(1) を使用すると、オブジェクトの依存関係の初期設定の順番を表示できます。たとえば、次の動的実行プログラムとその依存関係は、周期性のある依存関係を示しています。


$ dump -Lv B.so.1 | grep NEEDED
[1]     NEEDED      C.so.1
$ dump -Lv C.so.1 | grep NEEDED
[1]     NEEDED      B.so.1
$ dump -Lv main | grep NEEDED
[1]     NEEDED      A.so.1
[2]     NEEDED      B.so.1
[3]     NEEDED      libc.so.1
$ ldd -i main
        A.so.1 =>        ./A.so.1
        B.so.1 =>        ./B.so.1
        libc.so.1 =>     /usr/lib/libc.so.1
        C.so.1 =>        ./C.so.1
        libdl.so.1 =>    /usr/lib/libdl.so.1
 
   init library=./A.so.1
   init library=./C.so.1 (cyclic dependency on ./B.so.1)
   init library=./B.so.1 (cyclic dependency on ./C.so.1)
   init library=/usr/lib/libc.so.1

環境変数 LD_BREADTH は、空文字以外の値に設定し、強制的に実行時リンカーに、2.5.1 以前の順序で .init セクションを実行させます。

初期設定処理は、dlopen(3X) が指定された実行中のプロセスに追加されたオブジェクトごとに繰り返されます。

アプリケーションの依存関係の終了ルーチンは、atexit(3C) によって記録できるように構成されます。これらのルーチンは、プロセスが exit(2) を呼び出したとき、またはオブジェクトが、dlclose(3X) が指定された実行プロセスから除去されたときに呼び出されます。

Solaris 2.6 リリースからは、終了ルーチンが依存関係の配列順に呼び出されます。

Solaris 2.5.1 以前のリリースの場合、または LD_BREADTH 環境変数が実行されている場合には、終了ルーチンは読み込みされた順に呼び出されていました。

この初期設定および終了の呼び出し順序は、簡単明瞭に見えますが、この順序を強調しすぎないように注意が必要です。オブジェクトの順序は、共有オブジェクトとアプリケーションの開発によって左右される場合があるからです (詳細については、「依存関係の並べ変え」を参照)。


注 -

動的実行プログラム内の .init または .fini セクションは、コンパイラドライバから提供された、プロセスの始動と終了メカニズムによってアプリケーション自体から呼び出されます。動的実行プログラムの .init セクションは、その依存関係 .init セクションがすべて実行されてから、最後に呼び出されます。動的実行プログラムの .fini セクションは、その依存関係の .fini セクションが実行される前に、一番最初に呼び出されます。