Linux系统下,程序的函数库,可以使用静态库,也可以使用动态库,在编译应用程序时,静态库被直接编译进可执行文件使用,动态库在程序执行时通过动态加载的方式使用。
一:将源码编译为动态库
使用gcc编译套件将源代码文件编译为动态库文件,需要使用如下命令:
gcc test.c -fPIC -shared -o libtest.so
-o参数指定生成的动态库文件名称为 libtest.so
-fPIC 参数表示生成位置无关的 .o文件,这些.o文件可以用来链接成动态库so
(与-fPIC类似的有另外一个参数-fPIE, 表示生成的.o文件不能链接成so库文件,只能链接成可执行文件)
-shared参数表示将.o文件链接成动态库so文件
二:编译时使用动态库文件
使用gcc编译应用程序时,可以通过使用-L参数指定库文件所在路径, -l参数指定库文件名称引入库文件。
对于静态库和动态库,gcc编译时引入方式一样。
gcc在链接静态库时,库搜索路径遵循以下原则
1:-L参数指定的路径。
2:环境变量LIBRARY_PATH指定的路径。
3:系统默认路径/lib; /usr/lib; /usr/local/lib
gcc在编译时,动态库的搜索路径与静态库的搜索原则一致。
三:程序在运行期间动态库使用
静态库在编译时已经被链接进可执行文件,不存在在运行期间加载的问题,但对于动态库,应用程序在运行期间,需要重新加载库文件。
在运行期间,动态库的加载顺序如下:
1:根据ELF程序DT_PATH段中描述的路径信息,在对应路径搜索动态库文件。
2:根据环境变量LD_LIBRARY_PATH配置的路径信息,搜索动态库文件。
3:根据/etc/ld.so.cache中缓存的路径文件,搜索库文件。
4:在系统默认路径/lib; /usr/lib下搜索库文件。
说明:
ELF程序DT_PATH段中的路径信息,需要在程序编译链接时指定,使用gcc进行编译链接程序时,通过指定参数 “-Wl, -rpath”;指定多个路径时设置格式如下:
-Wl, -rpath=/opt/lib:/opt/lib64
/etc/ld.so.cache文件记录了程序搜索的so库路径,该文件由ldconfig工具根据/etc/ld.so.conf生成;当增加了新的动态库搜索路径后,可以修改/etc/ld.so.conf,然后执行ldconfig刷新/etc/ld.so.cache内容。
四:代码编写时,通过动态库函数接口在代码中导入动态库并使用动态库中的相关函数
动态库的使用,还有一种额外的方式,即通过相关接口函数,直接在程序运行期间完成,这种方式在程序编译期间,不需要提供库函数的头文件或so文件,由程序员编码使用。
1:通过dlopen函数打开一个so文件并加载进内存中。
2:通过dlsym函数获取动态库中的函数指针并调用对应函数。
3:通过dlclose关闭打开的so文件。
4:通过dlerror获取操作失败错误码。
五:其他相关工具
ldd命令检查可执行程序或其他动态库所依赖的其他动态库。
ldconfig工具用于管理动态库搜索缓存文件/etc/ld.so.cache, 该工具会读取/etc/ld.so.conf; /etc/ld.so.conf.d内容并刷新/etc/ld.so.cache内容。
nm命令可以列出一个函数库中的符号表信息,从而判断对应的接口函数是否存在。
objdump可显示目标文件信息,也可反汇编目标文件,查看符号信息等。