.\" This source code is a product of Sun Microsystems, Inc. and is provided .\" for unrestricted use provided that this legend is included on all tape .\" media and as a part of the software program in whole or part. Users .\" may copy or modify this source code without charge, but are not authorized .\" to license or distribute it to anyone else except as part of a product or .\" program developed by the user. .\" .\" THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC. .\" SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY .\" OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT .\" EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS .\" ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN .\" NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT, .\" INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING .\" FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY. .\" .\" This source code is provided with no support and without any obligation on .\" the part of Sun Microsystems, Inc. to assist in its use, correction, .\" modification or enhancement. .\" .\" SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE .\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS .\" SOURCE CODE OR ANY PART THEREOF. .\" .\" Sun Microsystems, Inc. .\" 2550 Garcia Avenue .\" Mountain View, California 94043 .\" .\" Copyright (c) 1991 Sun Microsystems, Inc. .\" .\" @(#) dlopen.3 1.6 90/01/31 SMI .\" %FreeBSD: src/lib/libc/gen/dlopen.3,v 1.8.2.7 2001/12/14 18:33:51 ru Exp % .\" $FreeBSD$ .\" .\" WORD: directed acyclic graph 有向非巡回グラフ .Dd September 24, 1989 .Os .Dt DLOPEN 3 .Sh 名称 .Nm dlopen , dlsym , dlerror , dlclose .Nd 動的リンカへのプログラムのインタフェース .Sh ライブラリ .Lb libc .Sh 書式 .In dlfcn.h .Ft void * .Fn dlopen "const char *path" "int mode" .Ft void * .Fn dlsym "void *handle" "const char *symbol" .Ft const char * .Fn dlerror "void" .Ft int .Fn dlclose "void *handle" .Sh 解説 これらの関数は、動的リンカサービスに対する単純なプログラムの インタフェースを提供します。 プログラムのアドレス空間に新しい共有オブジェクトを追加する操作、 共有オブジェクトが定義するシンボルのアドレス結合を取得する操作、 および共有オブジェクトを使用する必要がなくなったときに それを除去する操作が提供されています。 .Pp .Fn dlopen は、 .Fa path 内の共有オブジェクトへのアクセスを提供し、 .Fn dlsym と .Fn dlclose の呼び出しにおいて、オブジェクトを後で参照するために使用可能な 記述子を返します。 .Fn dlopen を呼び出す前に .Fa path がアドレス空間内になかった場合はアドレス空間に配置されます。 この方法で、オブジェクトが 初めてアドレス空間にロードされるとき、関数 .Fn _init が存在すればそれが動的リンカによって呼び出されます。 先の .Fn dlopen 呼び出しでアドレス空間内に .Fa path が既に配置されている場合、2 度目は追加されません。 しかし、 .Fa path 上での .Fn dlopen 操作の参照カウント値は管理されます。 .Fa path に指定されたものが NULL ポインタであれば、プロセスの メイン実行可能モジュールへの参照として解釈されます。 .Fa mode は、ロードされたオブジェクトからの外部関数への参照が、 どのようにその参照先と結合するか、その方法を制御します。 これには次の値のうちの 1 つが含まれていなくてはなりません。 おそらくは、後で述べる追加フラグとの OR をとった値に なるでしょう。 .Bl -tag -width RTLD_LAZYX .It Dv RTLD_LAZY 外部関数への参照はそれぞれ関数が最初に呼び出されるときに解決されます。 .It Dv RTLD_NOW 外部関数への参照はすべて .Fn dlopen によってただちに結合されます。 .El .Pp .Dv RTLD_LAZY は、効率を良くするという理由で一般的に好ましいです。しかし、 .Fn dlopen を呼び出している間に未定義シンボルを確実に発見するためには .Dv RTLD_NOW が便利です。 .Pp 次のフラグの 1 つを OR をとって .Fa mode 引数の中に含めることができます。 .Bl -tag -width RTLD_GLOBALX .It Dv RTLD_GLOBAL この共有オブジェクトから得られるシンボルおよび 必要とされるオブジェクトの有向非巡回グラフ (DAG) が、 その他すべての共有オブジェクトからの未解決の参照を 解決するために利用可能になります。 .It Dv RTLD_LOCAL この共有オブジェクトから得られるシンボルおよび 必要とされるオブジェクトの有向非巡回グラフ (DAG) が、 同一の共有オブジェクトからの未解決の参照を 解決するために利用可能になります。 こちらがデフォルトの動作ですが、このフラグを用いて 明示的に指定することができます。 .El .Pp .Fn dlopen は、処理が失敗すると NULL ポインタを返し、 .Fn dlerror で問い合わせできるエラー状態を設定します。 .Pp .Fn dlsym は、 .Fa symbol が .Fa handle で識別される共有オブジェクト内で 発生したときと同様に、ヌル文字で終了する文字列 .Fa symbol で記述されたシンボルのアドレス結合を返します。 .Fn dlopen によってアドレス空間に追加されたオブジェクトによってエクスポートされる シンボルは、 .Fn dlsym 呼び出しを通してのみアクセス可能です。 このようなシンボルは、オブジェクトがロードされる際に、すでに アドレス空間に存在しているシンボルの定義に置き換わるものでは ありませんし、通常の動的リンク参照を満たすために利用可能な ものでもありません。 .Pp .Fn dlsym が特別な .Fa handle .Dv NULL を使用して呼び出された場合は、 そのハンドルは呼び出しがされている実行ファイルあるいは 共有オブジェクトへの参照として解釈されます。このため、 共有オブジェクトは自分自身の持つシンボルを 参照できるのです。 .Pp .Fn dlsym が特別な .Fa handle .Dv RTLD_DEFAULT を使用して呼び出された場合は、オブジェクトが ロードされる際に未定義のシンボルを解決するために 使用されるアルゴリズムに従ってシンボルを探索します。 探索されるオブジェクトは次のように書かれた順番になります。 .Bl -enum .It 参照しているオブジェクト自身 (あるいは .Fn dlsym への呼び出しがされているオブジェクト)。ただし、オブジェクトが .Xr ld 1 に対して .Fl Wsymbolic オプションを使用してリンクされた場合。 .It プログラムの起動時にロードされていた全オブジェクト .It .Fn dlopen 経由でロードされた全オブジェクト。これらのオブジェクトは、 参照を行っているオブジェクトも含んだ、必要とされるオブジェクトの 有向非巡回グラフに存在します。 .It .Dv RTLD_GLOBAL フラグを .Fa mode 引数で設定して呼び出した .Fn dlopen 経由でロードされた全オブジェクト .El .Pp .Fn dlsym が特別な .Fa handle .Dv RTLD_NEXT を使用して呼び出された場合、シンボルの検索は、 .Fn dlsym 呼び出しを発行した後でロードされた共有オブジェクトに制限されます。 そのため、メインプログラムからこの関数が呼び出された場合、 すべての共有ライブラリが検索されます。この関数が共有ライブラリから 呼び出された場合、 その共有ライブラリより後でロードされる共有ライブラリすべてが 検索されます。 .Dv RTLD_NEXT はライブラリ関数を包み込むラッパを実装するのに便利です。 例えば、ラッパ関数 .Fn getpid がある場合、関数内で .Li dlsym(RTLD_NEXT, \&"getpid\&") を使用すれば .Dq 本物の .Fn getpid にアクセスできるでしょう。 .Pp シンボルが見つけられなかった場合、 .Fn dlsym は null ポインタを返し、エラー状態を設定します。 エラー状態は .Fn dlerror を使用して問い合わせることができます。 .Pp .Fn dlerror は、 .Fn dlopen , .Fn dlsym , または .Fn dlclose 呼び出しの間に発生した最後のエラーを記述する ヌル文字で終了する文字列を返します。 このようなエラーが発生していない場合、 .Fn dlerror は NULL ポインタを返します。 .Fn dlerror を呼び出すたびに、エラー指示がリセットされます。 そのため、後の呼び出しが先の呼び出しの直後にくるような .Fn dlerror 呼び出しを行った場合、後の呼び出しでは必ず NULL ポインタが 返ってきます。 .Pp .Fn dlclose は .Fa handle が参照する共有オブジェクトへの参照を削除します。 参照カウント値が減らされ 0 になると、そのオブジェクトはアドレス空間から 削除され .Fa handle は無効になります。この方法で共有オブジェクトを除去する直前に、 .Fn _fini 関数がこのオブジェクトで定義されている場合には それを呼び出します。 .Fn dlclose は、処理が成功すると値 0 を返します。 そうでない場合は -1 を返し、 エラー状態を設定します。エラー状態は .Fn dlerror で問い合わせできます。 .Pp オブジェクトに固有の関数 .Fn _init と .Fn _fini は、引数なしに呼び出され、戻り値は期待されていません。 .Sh 注 ELF 実行可能ファイルの場合、 ファイル中で定義されているシンボルを .Fn dlsym で見えるようにするには .Xr ld 1 に対して .Fl export-dynamic オプションを使用してリンクを行う必要があります。 .Pp 以前の実装では、C 言語からコンパイルしたオブジェクトコードと シンボルの互換性を持たせることができるように、 外部シンボルにはすべてアンダスコアを先頭につける必要が ありました。現在でも、 C 言語のコンパイラに対して (非推奨ですが) .Fl aout オプションを使用した場合には当てはまります。 .Sh エラー .Fn dlopen と .Fn dlsym は、エラーが発生した場合には NULL ポインタを返します。 .Fn dlclose は処理が成功すると 0 を返し、 エラーが発生した場合は -1 を返します。 エラーが検出されるたびに、エラーの詳細を説明するメッセージが .Fn dlerror 呼び出しによって取り出せます。 .Sh 関連項目 .Xr ld 1 , .Xr rtld 1 , .Xr dladdr 3 , .Xr link 5