追加オブジェクトは、dlopen(3C) を使用して、実行プロセスのアドレススペースに追加できます。この関数は、引数としてファイル名と結合モードを入手し、アプリケーションにハンドルを戻します。このハンドルを使用すると、アプリケーションは、dlsym(3C) を使用することによってシンボルを配置できます。
パス名が、単純ファイル名で指定されている (名前の中に「/」が組み込まれていない) 場合、実行時リンカーは一連の規則を使用して、適切なパス名を生成します。「/」が組み込まれたパス名は、そのまま使用されます。
これらの検索パスの規則は、最初の依存関係の配置に使用された規則と全く同じものです。「実行時リンカーが検索するディレクトリ」を参照してください。たとえば、ファイル main.c には、次のようなコードフラグメントが組み込まれているとします。
#include <stdio.h> #include <dlfcn.h> int main(int argc, char ** argv) { void * handle; ..... if ((handle = dlopen("foo.so.1", RTLD_LAZY)) == NULL) { (void) printf("dlopen: %s\n", dlerror()); return (1); } ..... |
実行時リンカーは、共有オブジェクト foo.so.1 を検索するために、プロセスの初期設定時に存在する任意の LD_LIBRARY_PATH 定義を使用します。続いて、実行時リンカーは prog のリンク編集時に指定された「実行パス」を使用します。最後に、実行時リンカーは 32 ビットオブジェクトの場合は /lib と /usr/lib、64 ビットオブジェクトの場合は /lib/64 と /usr/lib/64 のデフォルト位置を使用します。
パス名が次のように指定されているとします。
if ((handle = dlopen("./foo.so.1", RTLD_LAZY)) == NULL) { |
実行時リンカーは、プロセスの現在のカレントディレクトリ内でこのファイルだけを検索します。
dlopen(3C) を使用して指定された共有オブジェクトは、「そのバージョンのファイル名」で参照することをお勧めします。バージョン管理の詳細については、「バージョン管理ファイル名の管理」を参照してください。
必要なオブジェクトを配置できない場合は、dlopen(3C) によって NULL ハンドルが戻されます。この場合、dlerror(3C) を使用すると、失敗した真の理由を表示できます。次に例を示します。
$ cc -o prog main.c $ prog dlopen: ld.so.1: prog: fatal: foo.so.1: open failed: No such \ file or directory |
dlopen(3C) によって追加されたオブジェクトに、ほかのオブジェクトに依存する関係がある場合、その依存関係もプロセスのアドレススペースに配置されます。このプロセスは、指定されたオブジェクトの依存関係がすべて読み込まれるまで継続されます。この依存関係のツリーを「グループ」と呼びます。
dlopen(3C) によって指定されたオブジェクト、またはその依存関係が、すでにプロセスイメージの一部である場合は、そのオブジェクトはこれ以上処理されません。この場合でも有効なハンドルは、アプリケーションに戻されます。このメカニズムにより、同じオブジェクトが複数回読み込まれることを防ぐことができます。また、このメカニズムを使用すると、アプリケーションは専用のハンドルを入手できます。たとえば、前述の例で main.c に次の dlopen() 呼び出しが含まれている場合があります。
if ((handle = dlopen(0, RTLD_LAZY)) == NULL) { |
この dlopen(3C) から返されたハンドルを使用すれば、アプリケーション自身の内部、プロセスの初期設定中に読み込まれたすべての依存関係内、またはプロセスのアドレススペースに追加されたすべてのオブジェクト内で、シンボル検索を行えます。それには、dlopen(3C) で RTLD_GLOBAL フラグを指定します。