.so, .la和.a库文件之间的区别是什么?

我知道.so文件是一种动态库(许多线程可以共享这样的库,所以不需要在内存中有多个副本)。但是.a.la之间的区别是什么?这些都是静态库吗?

如果动态库比静态库有更大的优势,为什么还有很多静态库呢?什么时候我应该尝试在.so.a中构建代码?

[mirror@home ins_openvpn]$ ls lib/openvpn/plugins/ -l
total 96
-rw-r--r-- 1 mirror mirror 22892 Sep  2 23:25 openvpn-plugin-auth-pam.a
-rwxr-xr-x 1 mirror mirror   931 Sep  2 23:25 openvpn-plugin-auth-pam.la
-rwxr-xr-x 1 mirror mirror 23621 Sep  2 23:25 openvpn-plugin-auth-pam.so
-rw-r--r-- 1 mirror mirror 17228 Sep  2 23:25 openvpn-plugin-down-root.a
-rwxr-xr-x 1 mirror mirror   932 Sep  2 23:25 openvpn-plugin-down-root.la
-rwxr-xr-x 1 mirror mirror 18805 Sep  2 23:25 openvpn-plugin-down-root.so
152561 次浏览

文件类型分解

.so文件是动态库.;后缀代表“共享对象”,因为所有与库链接的应用程序都使用相同的文件,而不是在结果可执行文件中复制。

.a文件是静态库。后缀代表"archive",因为它们实际上只是原始.o对象文件的存档(由ar命令组成——tar的前身,现在只用于创建库)。

.la文件是GNU "libtools"包来描述组成相应库的文件。你可以在这个问题中找到更多关于它们的信息:libtool's .la文件是做什么的?

静态vs动态

静态

  • :用户总是使用你用应用程序测试过的库版本,所以不应该有任何令人惊讶的兼容性问题。

  • 反对:如果一个库中的问题被修复,你需要重新分发你的应用程序来利用它。但是,除非它是一个用户可能自行更新的库,否则无论如何您都可能需要这样做。

动态

  • :你的进程的内存占用更小,因为用于该库的内存在使用该库的所有进程之间摊销。

  • :库可以在运行时按需加载;这对插件很有好处,所以在编译和安装软件时不必选择要使用的插件。新插件可以动态添加。

  • 反对:在某人试图安装应用程序的系统上,库可能不存在,或者他们的版本可能与应用程序不兼容。为了缓解这种情况,应用程序包可能需要包含库的副本,以便在必要时安装它。包管理器可以下载和安装任何必要的依赖项,这通常也可以缓解这一问题。

  • 反对:链接时间优化通常是不可能的,所以在高性能应用程序中可能会有效率影响。参见维基百科关于WPO和LTO的讨论。

动态库对系统库特别有用,比如libc。这些库通常需要包含依赖于特定操作系统和版本的代码,因为内核接口已经发生了变化。如果将程序与静态系统库链接,则该程序将只在该库版本所针对的操作系统版本上运行。但是如果您使用动态库,它将自动拾取安装在您运行的系统上的库。

在给出答案的基础上,也可以说静态库就像一个目标文件的集合。当调用静态库中的函数或其他任何东西时,链接器在库中搜索被引用的项,并将定义被引用项的目标文件添加到可执行文件中。另一方面,共享库就像一个大的对象文件,由所有其他对象文件组成。因此,如果你在共享库中调用一个符号,那么所有的object文件都会在可执行文件中被引用。