QAH*_*QAH 23 linux windows shared-libraries
我有一个关于Windows共享库(DLL)与Linux共享库(SO)的快速问题.
为什么在创建Windows DLL时它需要客户端程序也链接到静态库(.lib文件),但在Linux中创建的应用程序不需要任何链接来防止这种静态库.
它与代码重定位等有什么关系吗?谢谢.
dat*_*olf 34
为什么在创建Windows DLL时它需要客户端程序也链接到静态库(.lib文件),但在Linux中创建的应用程序不需要任何链接来防止这种静态库.
这是Microsoft做出的历史性设计决策,因此链接器可以将DLL引用添加到可执行文件中,而不会在链接时出现DLL的特定版本.原因是,总有不同版本的Windows,不同版本的DLL.当时微软还在OS/2上与IBM合作,计划是,Windows程序也可以在OS/2上执行.好吧,微软决定通过推出基于NT内核的专业级操作系统来"反弹"OS/2.但这意味着,对于开发,您希望开发人员能够链接到系统DLL,而无需提供DLL的所有不同变体.相反,动态链接"模板"将用于创建DLL和可执行文件(都是PE格式),这些是特定.lib文件,根本不是库,而只是符号和序数表(这是一个鲜为人知的事实,但PE二进制符号不仅可以通过字符串标识符加载,还可以加载整数,即所谓的序数.
序数的副作用是,它们允许隐藏人类可读的符号,这样只有在您知道序数←→函数关系时才能使用DLL.
在Unix中,传统是"你在将要运行它的系统上构建它",或者"你有所有目标系统文件".所以从来没有激励这么独立的图书馆和联系信息.从技术上讲,同样适用于DLL也是如此.PE可以导出DLL所执行的符号和重定位表,并且链接器可以从中获取所需的所有信息,就好了.
如果要使用Unix共享对象隐藏符号,通常使用包含struct其中所有函数指针的单个符号来执行此操作,并且仅按名称导出此结构的全局常量实例,其中包含大量未明确命名的指针.但是,您可以对Windows DLL执行完全相同的操作.
TL; DR:其原因不是技术问题,而是营销和分销决策.
rod*_*igo 23
实际上不是代码重定位,这是一个完全不同的问题.它与建筑有所不同:
在Windows中,DLL就像可执行文件(EXE).EXE和DLL之间的主要区别在于EXE具有入口点(main/WinMain函数),因此它可用于启动进程,而DLL只能加载到预先存在的进程中.但是看(1)
在Linux中,.so的工作类似于静态库(.a).主要区别在于.so文件可以与正在运行的程序链接,而.a文件只能在编译程序时链接.
这种方法的结果是在linux中可以使用相同的文件来构建和运行程序.但是在Windows中,您需要一个适当的库(LIB)来链接程序.实际上,对应于DLL的lib通常只有函数的名称,以满足链接器,以及执行重定位的存根.但见(2)
(1)嗯,DLL也有入口点,但它不用作主函数,就像某种初始化/终结钩子一样.
(2)一些链接器足够智能,在某些简单的情况下,能够通过使用DLL本身链接到DLL,而无需额外的LIB文件.我认为至少MinGW链接器可以做到这一点.