前言
-
在手动设置动态库的存放路径的情况下,发现 musl ldso 依旧可以加载位于
/lib
目录下的 动态共享库 -
动态库的存放路径或者说搜索路径,是否可以手动配置?比如 Linux 上 有个配置文件可以配置,可以改变 动态库的搜索次序,musl ldso 是否也可以做到这一点?
搜索路径
- 通过查看 musl 的代码:
ldso\dynlink.c
中的load_library
函数中实现,了解到,musl 的动态库默认是以lib
作为前缀的,并且不能使用系统预留的 动态库名字,比如libc.so
- musl ldso 通过应用程序的 动态库依赖列表获取依赖的动态库名字,大部分是没有路径的。
- 下面是动态库路径的处理:
-
通过这里发现,当前 平台
LDSO_ARCH
如果为aarch64
时,如果存在/etc/ld-musl-aarch64.path
文件,就读取这个文件,获取 sys_path,也就是动态库的搜索路径 -
动态库的搜索路径不只是一个,可以使用
:
冒号分隔多个路径,这个 sys_path 路径是有先后次序的,前面的优先搜索。
环境变量
- 在
ldso\dynlink.c
中的__dls3
函数中,可以发现, env_path 与 env_preload 也是动态库搜索路径的环境变量,系统如果通过 setenv 设置了LD_LIBRARY_PATH
或者LD_PRELOAD
,也会改变 musl ldso 的搜索路径的次序
env_path = getenv("LD_LIBRARY_PATH");
env_preload = getenv("LD_PRELOAD");
-
当前了解到
LD_PRELOAD
设置的是动态库,这里的动态库也是使用:
冒号分隔,优先加载 -
如果设置了
LD_LIBRARY_PATH
,是动态库的搜索路径,可以是多个,:
冒号分隔,在ldso\dynlink.c
中的load_library
函数 发现比 系统路径执行的早。 -
以上都没有设置,并且有了
/etc/ld-musl-aarch64.path
文件,就读取/etc/ld-musl-aarch64.path
里面的路径作为系统动态库搜索路径 -
如果没有
/etc/ld-musl-aarch64.path
文件,就搜索 默认的sys_path = "/lib:/usr/local/lib:/usr/lib"
,这说明即使不设置,/lib
目录下的动态库可以被 musl ldso 搜索得到。 -
"/lib:/usr/local/lib:/usr/lib"
路径搜索次序为:/lib
->/usr/local/lib
->/usr/lib
LD_LIBRARY_PATH 设置方法
-
setenv("LD_LIBRARY_PATH", "/kernel:/home/lib:/hello/app", 1);
,这里设置环境变量LD_LIBRARY_PATH
,这样可以搜索的路径为:/kernel
->/home/lib
->/hello/app
-
注意
LD_LIBRARY_PATH
的设置不影响系统的动态库搜索路径,也就是LD_LIBRARY_PATH
搜索不到,依旧去系统的动态库路径下搜索
ld-musl-aarch64.path 设置方法
-
注意
ld-musl-aarch64.path
表示 aarch64 平台下的,不同的平台,注意名字"/etc/ld-musl-" LDSO_ARCH ".path"
-
测试方法: 把共享库 libt0.so 移动到其他的位置,如
/hello
目录下,此时运行 应用程序(依赖共享库 libt0.so),提示无法找到 依赖的共享库 -
新建 /etc 目录, 在 /etc 目录下 新建
ld-musl-aarch64.path
,内容 :/lib:/usr/local/lib:/usr/lib:/hello
,也就是增加了/hello
的路径 -
此时再次运行应用程序,正常运行,发现加载的共享库位置:
/hello/libt0.so
msh />./t0_test_s.elf
msh />Error loading shared library libt0.so: No such file or directory (needed by ./t0_test_s.elf)
librtthread.so : load map : 0x212000
Error relocating ./t0_test_s.elf: t0_data_set: symbol not found
Error relocating ./t0_test_s.elf: t0_data_get: symbol not found
msh />mkdir /etc
msh />cd /etc/
msh /etc>echo /lib:/usr/local/lib:/usr/lib:/hello /etc/ld-musl-aarch64.path
msh /etc>cat ld-musl-aarch64.path
/lib:/usr/local/lib:/usr/lib:/hello
msh />./t0_test_s.elf
msh />libt0.so : load map : 0x212000
librtthread.so : load map : 0x233000
/lib/librtthread.so : init_array : 0x235a60
/hello/libt0.so : init_array : 0x212750
./t0_test_s.elf : init_array : 0x2015d0
main : test start
main : -----------dlopen enter -----------
dl_test : ------------get-----------
dl_test : [get] ts.name = rt-smart_t0_lib_default
dl_test : [get] ts.cmd = 0xaabbccdd
dl_test : [get] ts.data = 0x8999eeff
main : -----------dlopen exit -----------
main : ------------get-----------
main : [get] ts.name = rt-smart_t0_lib_default
main : [get] ts.cmd = 0xaabbccdd
main : [get] ts.data = 0x8999eeff
main : ------------set->get-----------
main : [set-get] ts.name = t2_name_is_ok
main : [set-get] ts.cmd = 0x33559977
main : [set-get] ts.data = 0x4499aabb
main : test end
预加载库 LD_PRELOAD
- 当前 musl ldso 支持
"LD_PRELOAD"
环境变量,可以通过setenv("LD_PRELOAD", "/lib/aa.so:/lib/bb.so", 1);
设置需要提前加载的共享库。
小结
-
如果应用程序共享的库有优先级,可以把优先级高的放在搜索路径的前面,可以通过配置
/etc/ld-musl-aarch64.path
文件或者设置环境变量:setenv("LD_LIBRARY_PATH", "/kernel:/home/lib:/hello/app", 1);
-
如果几个动态库需要提前加载初始化,可以通过 设置
"LD_PRELOAD"
环境变量,这样提前加载的共享库优先加载