| ナビゲーションリンクをスキップ | |
| 印刷ビューの終了 | |
|
Oracle Solaris 11.1 リンカーとライブラリガイド Oracle Solaris 11.1 Information Library (日本語) |
7. システムのパフォーマンスを最適化するオブジェクトの構築
パート IV ELF アプリケーションバイナリインタフェース
拡張可能な機能を提供するプログラムは、多くの場合、実行時に dlopen() 関数を使用して読み込まれた共有オブジェクトを利用します。これらの共有オブジェクトは、多くの場合プラグインと呼ばれ、コアシステムの機能を拡張するための柔軟な手段を提供します。プラグインを読み込むオブジェクトは、親と呼ばれます。
親オブジェクトは、プラグインを読み込み、プラグイン内の関数やデータにアクセスします。また、一般に親オブジェクトはプラグインが使用する関数とデータを提供します。この例を、次の親およびプラグインのソースファイルで示します。ここで、親はプラグインのためにparent_callback() という名前の関数を提供しています。プラグインは、親が呼び出すための plugin_func() という名前の関数を提供しています。
$ cat main.c
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
void
parent_callback(void)
{
(void) printf("plugin_func() has called parent_callback()\n");
}
int
main(int argc, char **argv)
{
typedef void plugin_func_t(void);
void *hdl;
plugin_func_t *plugin_func;
if (argc != 2) {
(void) fprintf(stderr, "usage: main plugin\n");
return (1);
}
if ((hdl = dlopen(argv[1], RTLD_LAZY)) == NULL) {
(void) fprintf(stderr, "unable to load plugin: %s\n", dlerror());
return (1);
}
plugin_func = (plugin_func_t *) dlsym(hdl, "plugin_func");
if (plugin_func == NULL) {
(void) fprintf(stderr, "unable to find plugin_func: %s\n",
dlerror());
return (1);
}
(*plugin_func)();
return (0);
}
$ cat plugin.c
#include <stdio.h>
extern void parent_callback(void);
void
plugin_func(void)
{
(void) printf("parent has called plugin_func() from plugin.so\n");
parent_callback();
}
$ cc -o main main.c -lc
$ cc -Kpic -G -o plugin.so plugin.c -lc
$ ./main ./plugin.so
parent has called plugin_func() from plugin.so
plugin_func() has called parent_callback()
共有オブジェクトを作成するときは、オブジェクトがそのすべての依存関係を確実に指定できるように、-z defs オプションの使用をお勧めします。ただし、-z defs を使用すると、親オブジェクトからは満たされないシンボルがあるため、プラグインオブジェクトをリンクできなくなります。
$ cc -zdefs -Kpic -G -o plugin.so plugin.c -lc Undefined first referenced symbol in file parent_callback plugin.o ld: fatal: symbol referencing errors. No output written to plugin.so
parent_callback() シンボルが親オブジェクトによって提供されることをリンク編集に指定するには、mapfile を使用できます。
$ cat plugin.mapfile
$mapfile_version 2
SYMBOL_SCOPE {
global:
parent_callback { FLAGS = PARENT };
};
$ cc -zdefs -Mplugin.mapfile -Kpic -G -o plugin.so plugin.c -lc
プラグインを作成するときの対処方法としては、-z parent オプションを使用して、プラグインが親のシンボルに直接アクセスできるようにすることをお勧めします。mapfile の代わりに -z parent を使用すると、親オブジェクトの名前がプラグインの動的セクションに記録され、file ユーティリティーで表示されるという利点も得られます。
$ cc -zdefs -zparent=main -Kpic -G -o plugin.so plugin.c -lc
$ elfdump -d plugin.so | grep PARENT
[0] SUNW_PARENT 0xcc main
$ file plugin.so
plugin.so: ELF 32-bit LSB dynamic lib 80386 Version 1,
parent main, dynamically linked, not stripped