Linux LD_LIBRARY_PATH中空目录的作用
加载动态库测试
众所周知,Linux系统并未将可执行文件的同级目录,或者说工作目录列为依赖库的搜索路径。今天我心血来潮想验证一下是否真的如此,于是用Ubuntu22.04,以及一些动态库做了一个简单的测试,结果却发现了关于LD_LIBRARY_PATH之前从来不知道的一个点:空目录的作用。
用来测试的dm动态库。在/LoadTest/lib这个路径下,依赖了该目录下的一些动态库,例如libCalServer等。
使用ldd命令查看dm这个动态库的依赖项有没有找到
ldd libdm.so
居然惊奇的发现同级目录下的依赖项居然被搜索到了!这是怎么回事?
排除RUNPATH的影响
在Linux系统中,RUNPATH是一个可执行文件或共享库的属性,用于指定运行时动态链接器(ld.so)在加载程序时搜索共享库的路径。能找到同级目录下的依赖项是不是因为编译的时候指定的路径就是这个目录呢?
于是使用readelf命令查看该动态库的runpath
readelf -d libdm.so |grep PATH
output
0x000000000000001d (RUNPATH) Library runpath: [/cserver/cmake/../algos/lib:/cserver/lib]
让我感到奇怪的是这里面的路径并没有包含这些依赖库,而这个路径也没有包含$ORIGIN,故也不会搜索同级目录。
LD_LIBRARY_PATH的影响?
转念一想除了RUNPATH以外还有一个LD_LIBRARY_PATH的环境变量,该变量也会指定链接器去搜索动态库的路径,而且优先级比RUNPATH更高,难不成是它的影响?
查看当前系统重设置的LD_LIBRARY_PATH变量的值
echo $LD_LIBRARY_PATH
/cserver/lib:
果然是被设置了一个路径的。
export LD_LIBRARY_PATH=
于是将 LD_LIBRARY_PATH值为空以后,再次使用ldd命令查看该动态库依赖项。
ldd libdm.so
可以看到这次依赖的动态库都没有别搜索到,大功告成,终于能够确认默认是不会搜索同级目录的。
但是我突然发现了一个问题,就是之前LD_LIBRARY_PATH被设置的路径,也是一个不存在的路径!
那之前为什么同级目录下的依赖项会被搜索到呢?LD_LIBRARY_PATH设置的又不是这个同级目录!
难道是冒号的作用?
观察之前输出的LD_LIBRARY_PATH的值,发现和之前我常见到的LD_LIBRARY_PATH的值有一点不同的地方就是这个的结尾是一个:。于是我打算测试如果LD_LIBRARY_PATH就等于一个冒号会怎么样。
export LD_LIBRARY_PATH=:
echo $LD_LIBRARY_PATH
output
:
再次使用ldd命令:
ldd libdm.so
居然惊奇的发现,这次同级目录下的依赖项居然都被找到了!
切换工作目录到上级目录,再次加载该动态库:
cd ..
ldd lib/libdm.so
可以看到动态库所在同级目录下的依赖项又没有被搜索了(因为现在的工作目录为动态库所在目录的上级目录)。我又尝试了一下
export LD_LIBRARY_PATH=A::B
然后在dm的同级目录下,再次使用ldd命令,发现同级目录下的依赖项还是被搜索到了
至此我愈发觉得,LD_LIBRARY_PATH中的:会被解释为工作目录的同级目录。可是令人奇怪的是:难道不是多个路径之间的分割符吗?怎么会被解释为同级目录呢?既可以作为分隔符,也会被当做同级目录的会是不是太奇怪了一些?
原因是路径中的空目录
于是我找到Linux man page中关于ld.so的页面,其中果然有关于LD_LIBRARY_PATH的一些解释。
A list of directories in which to search for ELF libraries at execution time.
The items in the list are separated by either colons or semicolons, and there is no support for escaping either separator.
A zero-length directory name indicates the current working directory.
A zero-length directory name indicates the current working directory.
原因居然是这个!长度为零的目录名会被解释为当前的工作目录。/cserver/lib:这个最后的:表示后面还跟了一个长度为零的目录,所以说才能够找到同级目录下的那些依赖项。