小编典典

共享库(.so),静态库(.a)和DLL(.so)之间的区别?

linux

我参与了有关Linux库的一些辩论,并想确认一些事情。

以我的理解(如果我做错了请纠正我,稍后我将编辑我的文章)在构建应用程序时有两种使用库的方式:

  1. 静态库(.a文件):在链接时,会将整个库的副本放入最终应用程序中,以便调用方应用程序始终可以使用库中的功能
  2. 共享对象(.so文件):在链接时,仅通过相应的标头(.h)文件针对其API验证了对象。该库直到需要运行时才真正使用。

静态库的明显优点是它们允许整个应用程序独立运行,而动态库的优点是可以替换“
.so”文件(即:由于安全性而需要更新的情况)错误),而无需重新编译基本应用程序。

我听说有人对共享库和动态链接库(DLL)进行了区分,即使它们都是“
.so”文件。在Linux或任何其他POSIX兼容操作系统(即MINIX,UNIX,QNX等)上进行C / C
++开发时,共享库和DLL之间是否有区别?有人告诉我(到目前为止)一个关键的区别是共享对象仅在运行时使用,而DLL的共享必须首先在应用程序中使用dlopen()调用来打开。

最后,我还听到一些开发人员提到“共享档案”,据我了解,共享档案本身也是静态库,但从未被应用程序直接使用。相反,其他静态库将链接到“共享档案”,以将某些(但不是全部)功能/资源从共享档案中拉到正在构建的静态库中。

预先感谢大家的帮助。

更新资料


在向我提供这些术语的上下文中,必须学习Linux的一组Windows开发人员实际上使用了错误的术语。
我试图纠正它们,但是(不正确的)语言规范卡住了。

  1. 共享库:程序启动时自动链接到程序的库,并且作为独立文件存在。该库在编译时包含在链接列表中(即:LDOPTS+=-lmylib对于名为的库文件mylib.so)。 该库必须在编译时以及应用程序启动时存在。
  2. 静态库:静态库,在构建时就合并到单个程序中(包含大型应用程序),该单个应用程序包含应用程序代码和在构建程序时自动链接到程序中的库代码,而最终的二进制文件则同时包含两者主程序和库本身作为单个独立的二进制文件存在。该库在编译时包含在链接列表中(即:LDOPTS+=-lmylib对于名为mylib.a的库文件)。 该库必须在编译时存在。
  3. DLL:本质上与共享库相同,但不是在编译时包含在链接列表中,而是通过dlopen()/ dlsym()命令加载该库,因此不需要在构建时就存在该库来进行程序编译。 同样,该库不需要在应用程序启动或编译时出现(必需) ,因为仅在进行dlopen/ dlsym调用时才需要。
  4. 共享存档:本质上与静态库相同,但是使用“导出共享”和“ -fPIC”标志进行编译。该库在编译时包含在链接列表中(即:LDOPTS+=-lmylibS对于名为的库文件mylibS.a)。两者之间的区别是,如果共享库或DLL希望将共享归档文件静态链接到其自己的代码,并且能够使共享库中的函数可用于其他程序,而不仅仅是使用它们,则需要此附加标志。 DLL内部。当有人为您提供静态库并且您希望将其重新打包为SO时,这很有用。 该库必须在编译时存在。

附加更新

DLL”和“ shared library
之间的区别只是我当时工作的公司中的一种(懒惰,不准确的)口语(Windows开发人员被迫转移到Linux开发,并且这个术语陷入僵局),并遵循上述说明。

另外,在S“共享档案”的情况下,库名后的尾随“ ”文字只是该公司的惯例,而不是整个行业。


阅读 1482

收藏
2020-06-02

共1个答案

小编典典

我一直认为DLL和共享对象是同一事物的不同术语-Windows将它们称为DLL,而在UNIX系统上,它们是共享对象,并且通用术语-动态链接库-
涵盖了这两个对象(甚至包括在UNIX上打开.so称为dlopen()“动态库”。

它们确实仅在应用程序启动时链接,但是您对头文件的验证概念不正确。头文件定义了用于编译使用该库的代码所需的原型,但是在链接时,链接器会在库本身内部进行查找,以确保所需的功能确实存在。链接器必须在链接时在某处找到函数体,否则会引发错误。它还在运行时执行此操作,因为正如您正确指出的那样,自程序编译以来,库本身可能已更改。这就是为什么ABI稳定性在平台库中如此重要的原因,因为ABI的改变破坏了针对旧版本编译的现有程序。

静态库只是直接从编译器中提取的目标文件包,就像在项目编译过程中要构建自己的对象库一样,因此静态库以完全相同的方式被拉入并馈送到链接器,未使用的位是以完全相同的方式掉落。

2020-06-02