延迟装入可以提供替代 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 选项来生成利用延迟装入的所有目标文件。