查看源代码
出自Linux Wiki
对
动态库(.so)
的源代码
根据以下的原因,您无权限进行编辑这个页面操作:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
Linux中的.so文件类似于Windows中的DLL,是动态链接库,也有人译作共享库(因so的全称为Shared Object)。当多个程序使用同一个动态链接库时,既能节约可执行文件的大小,也能减少运行时的内存占用。<ref>[http://www.akkadia.org/drepper/dsohowto.pdf How To Write Shared Libraries]</ref> 对于用户而言,经常遇到的问题是某些应用程序找不到其需要的.so文件: error while loading shared libraries: ...: cannot open shared object file: No such file or directory 本文将主要围绕该问题展开,介绍so文件存放位置、版本命名方案等。欢迎补充其它信息。 ==存放位置== Linux中绝大多数.so文件都存放在''/lib''、''/usr/lib/''(见[[Linux目录结构]]),对于64位和32位共存的系统,32位的动态库可能会放在''/lib32''、''/usr/lib32'',完整的动态库存放路径列表可通过''/etc/ld.so.conf''文件配置。(如果修改了配置,需要用 ''/sbin/ldconfig'' 命令更新缓存) 应注意动态库搜寻路径并不包括当前文件夹,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到so的问题,如 ./chrome: error while loading shared libraries: libnss3.so.1d: cannot open shared object file: No such file or directory 此时可用'''LD_LIBRARY_PATH'''环境变量做临时设置,如: <source lang="bash"> LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./chrome </source> 也有些so文件是在程序执行时临时加载的(如插件),它们的路径就比较灵活,只要可执行文件能找到它就行了。 ==程序链接的动态库== 一个可执行文件链接了哪些动态库呢?在遇到“error while loading shared libraries”时,我们难免会对此产生好奇。 查看该信息的方法是通过ldd,如 $ ldd chrome linux-vdso.so.1 => (0x00007fff52dff000) libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f0caebe4000) libdl.so.2 => /lib/libdl.so.2 (0x00007f0cae9e0000) libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007f0cae7d6000) libXss.so.1 => /usr/lib/libXss.so.1 (0x00007f0cae5d3000) libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f0cae3c1000) librt.so.1 => /lib/librt.so.1 (0x00007f0cae1b9000) ....(略) 要想看系统还没找到的动态库,可以借用grep: $ldd chrome | grep 'not found' libnss3.so.1d => not found libnssutil3.so.1d => not found libsmime3.so.1d => not found libplc4.so.0d => not found libnspr4.so.0d => not found ==版本== 动态库的版本总是个问题,如果编译时链接的库和执行时提供的不一样,难免会导致程序的执行发生诡异的错误。为解决此问题,Linux系列的做法是这样的: 首先,每个so文件有一个文件名,如'''libABC.so.x.y.z''',这里ABC是库名称,''x.y.z''是文件的版本号,一般来说:<ref>[http://bbs.chinaunix.net/archiver/tid-927777.html ChinaUnix.net: Linux so文件命名规则的讨论]</ref> *第一位''x''表示了兼容性,''x''不一样的so文件是不能兼容的。 *第二位''y''的变化表示可能引入了新的特性(Feature),但总的来讲还是兼容的。 *第三位''z''的变化一般表示仅是修正了Bug。 *并非所有.so文件都遵循此规则,但其应用确实很普遍。 在系统中,会存在一些[[符号链接]], 如<ref>[https://lists.linux-foundation.org/pipermail/lsb-spec/1999-May/000251.html LSB-Spec邮件列表中的一封信:Shared Libraries and naming conventions]</ref>: libpam.so -> libpam.so.0.83.0 libpam.so.0 -> libpam.so.0.83.0 其中第一个主要在使用该库开发其它程序时使用,比如gcc想连接PAM库,直接连''libpam.so''就行了,不必在链接时给出它的具体版本。第二个则主要用在运行时,因为前面说了第一位版本一样的库是互相兼容的,所以程序运行时只要试图连接''libpam.so.0''就够了,不必在意其具体的版本。ldconfig可以自动生成这些链接。 那么编译程序时gcc在链接一个so文件(如''libpam.so'')时,如何知道该程序运行时链接哪个文件呢(上例中是''libpam.so.0'')?原来产生so文件时,可以指定一个'''soname''',一般形如'''libABC.so.x'''。<ref>[http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html Static, Shared Dynamic and Loadable Linux Libraries]</ref>人们编译可执行文件时,如果链接了某个so,存在可执行文件里的.so文件名并不是其全名,而是这个soname。比如上例中,这个soname就是''libpam.so.0''。回头看一下上节ldd的结果,可以印证这一现象。 有时还会看到形如'''libABCn.so''',即版本号出现在.so前面的库文件,如''libXaw6.so''。此类文件一般是为开发者着想,比如GTK+ 3已经推出,但很多开发者还是想用GTK+ 2开发软件。由于编译时只连接无版本号的.so文件,就只有把版本号放在''.so''前面了。 ==参考资料== <references /> [[Category: Linux基础]]
返回到
动态库(.so)
。
导航
首页
社区入口
当前事件
最近更改
随机页面
帮助
查看
页面
讨论
查看源代码
历史
个人工具
登录/创建账户
搜索
简体繁体转换
不转换
简体
繁體
工具箱
链入页面
链出更改
特殊页面