Linux C++ libdl.so dlfcn.h使用方法(dlopen()dlsym()dlclose()dlerror())(用于动态链接库操作)(懒加载立即加载)共享库符号动态库
Posted Dontla
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux C++ libdl.so dlfcn.h使用方法(dlopen()dlsym()dlclose()dlerror())(用于动态链接库操作)(懒加载立即加载)共享库符号动态库相关的知识,希望对你有一定的参考价值。
文章目录
dlfcn.h解析
“dlfcn.h” 是C语言中用于动态链接库操作的头文件。它定义了一些重要的函数和宏,其中最重要的函数有三个:
- dlopen():打开一个动态链接库文件并返回一个句柄,该句柄用于后续的操作,如查找符号、关闭库等。
- dlsym():在打开的动态链接库中查找指定的符号,并返回符号的地址。
- dlclose():关闭先前打开的动态链接库。
此外,还有一些其他的函数和宏,例如:
- dlerror():返回最近一次动态链接库操作的错误信息。
- RTLD_LAZY 和 RTLD_NOW:这些是 dlopen() 函数的可选参数,分别表示懒加载和立即加载动态链接库中的符号。
- RTLD_GLOBAL 和 RTLD_LOCAL:这些也是 dlopen() 函数的可选参数,分别表示符号的全局可见性和局部可见性。
这些函数和宏可以用于在运行时加载和卸载动态链接库,动态链接库的使用使得程序可以在运行时动态地加载和调用库函数,从而使得程序的可扩展性更强。
附加
dlsym是什么缩写?
“dlsym” 是 “Dynamic Linker Symbol” 的缩写。它是一个在 C 语言中用于动态加载库文件中的符号(函数、变量等)的函数。使用 dlsym() 函数,可以在运行时动态地查找和调用库中的符号,这样可以使得程序更加灵活和可扩展。
在 Unix-like 系统中,动态链接器在加载共享库时,会把库中的符号地址解析出来,并保存到一个符号表中。dlsym() 函数可以在这个符号表中查找符号的地址,并返回给调用方。因此,dlsym() 函数在实现动态链接时起到了关键的作用。
RTLD_LAZY 懒加载是什么?有什么利弊?
“RTLD_LAZY” 的缩写是 “Run-Time Loading with Lazy Binding”。这个标志告诉动态链接器在运行时懒惰地绑定符号引用,也就是在第一次使用符号时才加载并进行符号绑定。
在使用 RTLD_LAZY 标志打开共享库时,动态链接器将会在共享库中仅解析那些被直接使用的符号,而不会解析整个库的所有符号。这种延迟解析和绑定的方式可以提高程序的启动速度,因为共享库的大部分内容都不会被加载和解析,只有在需要使用的时候才会被加载。
需要注意的是,使用 RTLD_LAZY 标志可能会增加程序中未定义符号的数量,这可能会导致一些潜在的问题,如内存泄漏或者未定义的行为。因此,在使用 RTLD_LAZY 标志时需要谨慎,确保程序的正确性和稳定性。
RTLD_NOW 立即加载是什么?
“RTLD_NOW” 是 dlopen() 函数的一个标志,表示在运行时立即加载共享库中的所有符号,也称为"立即绑定"。使用 RTLD_NOW 标志打开共享库时,动态链接器会在加载共享库时就立即解析所有符号引用,并进行符号绑定。
与 RTLD_LAZY 不同,使用 RTLD_NOW 标志打开共享库时会立即加载和解析库中的所有符号,因此程序在启动时会花费更多的时间和内存资源。不过,这种方式可以避免使用延迟绑定时可能出现的一些问题,如懒加载导致的未定义符号等问题。
使用 RTLD_NOW 标志的另一个好处是,程序在运行时不需要再进行符号解析和绑定操作,因此可以提高程序的运行速度。在某些要求高性能的场景中,使用 RTLD_NOW 标志可能是一个不错的选择。
需要注意的是,使用 RTLD_NOW 标志打开共享库时可能会导致库之间的符号冲突或者版本不兼容等问题,因此在使用时需要进行谨慎评估和测试。
RTLD_GLOBAL是什么?(全局加载)
“RTLD_GLOBAL” 是 dlopen() 函数的一个标志,表示在打开共享库时将其中定义的符号全局可见,也就是说,共享库中的符号可以被后续打开的其他共享库所使用。使用 RTLD_GLOBAL 标志打开共享库时,共享库中定义的符号将会被添加到全局符号表中,以便其他共享库在后续加载时可以使用。
这种方式可以方便地实现共享库之间的符号共享,避免了多个共享库中出现相同符号定义而导致的符号冲突问题。在一些需要动态加载共享库且需要使用共享库中的符号的场景中,使用 RTLD_GLOBAL 标志可以方便地实现符号的共享和使用。
需要注意的是,使用 RTLD_GLOBAL 标志可能会带来一些安全风险,因为将共享库中的符号设置为全局可见可能会被滥用,导致安全漏洞的发生。因此,在使用 RTLD_GLOBAL 标志时需要进行谨慎评估和测试,确保程序的安全性和稳定性。
RTLD_LOCAL是什么?(本地加载、局部加载)(共享库和共享库之间不共享符号,避免符号混淆冲突)
“RTLD_LOCAL” 是 dlopen() 函数的一个标志,表示在打开共享库时将其中定义的符号限定为本地可见,也就是说,共享库中的符号只能被当前的共享库所使用。使用 RTLD_LOCAL 标志打开共享库时,共享库中定义的符号将只能在当前的共享库中使用,无法被其他共享库所使用。
这种方式可以避免共享库之间符号的冲突和混淆,提高程序的稳定性和可维护性。在一些需要使用共享库但是不需要共享符号的场景中,使用 RTLD_LOCAL 标志可以保证符号的隔离和独立性。
需要注意的是,使用 RTLD_LOCAL 标志可能会导致一些符号无法被正确解析和绑定,因为其他共享库无法使用当前共享库中的符号。因此,在使用 RTLD_LOCAL 标志时需要仔细评估程序的需求和共享库的依赖关系,确保符号的正确性和程序的稳定性。
共享库(Shared Library)是什么?
共享库(Shared Library),也叫动态库(Dynamic Library),是一种程序库的形式,可以在运行时动态加载到内存中,并被多个进程或程序共享使用。
与静态库不同,共享库在编译时并不会被链接到程序中,而是在程序运行时通过动态链接器动态加载到内存中,使程序可以调用共享库中的函数和使用共享库中的变量。共享库的一个重要特点是可以在多个程序中共享使用,这样可以节省系统内存,提高程序的性能和灵活性。
共享库一般是以动态链接库的形式存在,扩展名通常为.so(在类Unix系统中)或.dll(在Windows系统中),其内部的代码可以被多个进程或程序共享使用。使用共享库可以避免重复编写代码,降低程序的开发和维护成本。
需要注意的是,共享库在使用时需要注意版本兼容性和符号冲突等问题,以避免在程序运行时出现问题。
共享库的符号指的是什么?全局符号和局部符号
共享库中的符号是指共享库中的变量、函数、类等可供外部程序使用的标识符,它们可以通过符号名称在程序中进行调用和使用。共享库中的符号可以分为两类:全局符号和局部符号。
-
全局符号是指在共享库中定义的可以被其他共享库和主程序使用的符号,这些符号在编译时会被加入到共享库的全局符号表中,并且可以通过 dlopen() 和 dlsym() 等函数在程序运行时动态加载和使用。全局符号可以通过设置 RTLD_GLOBAL 标志来使其在其他共享库中可见,以实现符号共享的目的。
-
局部符号是指在共享库中定义的只能被本地共享库中的其他符号所使用的符号,这些符号在编译时不会被加入到全局符号表中,只能在本地共享库内部进行使用。局部符号可以通过设置 RTLD_LOCAL 标志来限制其在本地共享库中可见,以避免符号冲突和混淆的问题。
共享库中的符号是共享库在程序中的重要特性,可以通过符号名称和动态链接器实现程序的动态加载和运行时链接,提高程序的灵活性和可维护性。
云从加载共享库用的什么方案?
他们用的懒加载和本地加载(局部加载)的方式
代码示例:演示如何使用 dlopen()、dlsym()、dlclose()、dlerror() 函数来动态加载共享库,并使用懒加载和 RTLD_LOCAL 标志
下面是一个简单的 C++ 代码示例,演示了如何使用 dlopen()、dlsym()、dlclose()、dlerror() 函数来动态加载共享库,并使用懒加载和 RTLD_LOCAL 标志:
#include <iostream>
#include <dlfcn.h>
int main()
// 使用 dlopen() 函数打开共享库 libtest.so,并以懒加载和 RTLD_LOCAL 标志打开
void* handle = dlopen("./libtest.so", RTLD_LAZY | RTLD_LOCAL);
if (!handle)
std::cerr << "Error loading shared library: " << dlerror() << std::endl;
return 1;
// 使用 dlsym() 函数查找共享库中的函数 my_function,并将其转换为函数指针
void (*my_function)() = (void (*)())dlsym(handle, "my_function");
if (!my_function)
std::cerr << "Error loading symbol: " << dlerror() << std::endl;
dlclose(handle);
return 1;
// 调用共享库中的函数 my_function
(*my_function)();
// 使用 dlclose() 函数关闭共享库
dlclose(handle);
return 0;
这个示例代码打开名为 libtest.so 的共享库,然后使用 dlsym() 函数查找其中的 my_function 函数,并将其转换为函数指针。接着,程序通过函数指针调用共享库中的函数 my_function。最后,程序使用 dlclose() 函数关闭共享库。
在这个示例代码中,dlopen() 函数以 RTLD_LAZY | RTLD_LOCAL
标志打开共享库,表示使用懒加载和局部符号的方式打开共享库。这意味着共享库中的符号只能在当前共享库中使用,且在运行时才会被动态加载和解析。如果符号在共享库中未定义或者存在错误,可以通过 dlerror() 函数获得相应的错误信息。
以上是关于Linux C++ libdl.so dlfcn.h使用方法(dlopen()dlsym()dlclose()dlerror())(用于动态链接库操作)(懒加载立即加载)共享库符号动态库的主要内容,如果未能解决你的问题,请参考以下文章