リンカーとライブラリ

dlopen() の代替手段の提供

遅延読み込みは、dlopen(3C)dlsym(3C) を使用する代わりになります。「実行時リンクのプログラミングインタフェース」を参照してください。たとえば、libfoo.so.1 の次のコードは、オブジェクトが読み込まれることを確認し、そのオブジェクトのインタフェースを呼び出します。


void foo()
{
    void * handle;

    if ((handle = dlopen("libbar.so.1", RTLD_LAZY)) != NULL) {
        int (* fptr)();

        if ((fptr = (int (*)())dlsym(handle, "bar1")) != NULL)
            (*fptr)(arg1);
        if ((fptr = (int (*)())dlsym(handle, "bar2")) != NULL)
            (*fptr)(arg2);
        ....
}

このコードは、必要なインタフェースを提供するオブジェクトが次の条件を満たす場合に、単純化できます。

遅延読み込みを活用することで、libbar.so.1 の同じ据え置き読み込みをアーカイブできます。この場合、関数 bar1() を参照すると、関連依存関係が遅延読み込みされます。さらに、標準関数呼び出しを使用すると、コンパイラまたは lint(1) 確認が提供されます。


void foo()
{
    bar1(arg1);
    bar2(arg2);
    ....
}
$ cc -G -o libfoo.so.1 foo.c -L. -zlazyload -zdefs -lbar -R'$ORIGIN'

ただし、必要なインタフェースを提供するオブジェクトが常に利用できるとは限らない場合、このモデルは失敗します。この場合、依存関係の名前なしで依存関係の有無をテストする機能が必要です。関数参照を満足する依存関係を使用できるかどうかをテストする手段が必要になります。

RTLD_PROBE ハンドルのある dlsym(3C) は、依存関係の有無および読み込みの確認に使用できます。たとえば、bar1() への参照は、リンク編集時に確立された遅延依存関係を利用できるかどうかを確認します。このテストは、dlopen(3C) が使用されたのと同じ方法で、依存関係が提供する関数への参照を制御するために使用できます。


void foo()
{
    if (dlsym(RTLD_PROBE, "bar1")) {
        bar1(arg1);
        bar2(arg2);
        ....
}

このテクニックは、標準関数呼び出しを使用するとともに、記録された依存関係の安全な据え置き読み込みを実現します。


注 –

この特別なハンドル RTLD_DEFAULT は、RTLD_PROBE の使用時と同じようなメカニズムを提供します。ただし、RTLD_DEFAULT を使用すると、存在しないシンボルを特定しようとして、処理中の遅延読み込みオブジェクトが保留されることがあります。この読み込みによって、依存関係を完全には定義していないオブジェクトを補います。ただし、これにより遅延読み込みの利点が失われることがあります。

遅延読み込みを使用するオブジェクトの作成には、-z defs オプションの使用をお勧めします。