WIN下和LINUX动态库的区别
**************************************************************************************************************************************
转载:http://blog.codingnow.com/2006/11/windows_unix_dynamic_library.html
最近慢慢将开发环境转向了 freebsd ,渐渐的发现了许多东西跟 Windows 下不太一样。我指的是,跟我以前想当然的理解不太一样。比如,unix 下对动态链接库 so 的处理,和 Windows 下的 DLL 就不太相同。
之前,我对 Windows 下更为了解一些。早几年做 Windows 开发,老是为动态链接,静态链接这些问题纠缠不清;慢慢的才有了比较清晰的理解,现在基本上不会为这类问题困绕了。前段时间,碰到一些朋友写 lua 的扩展库(windows 版本)时遇到的几个 bug ,就是因为链接问题导致的。公司内部的一个项目,在服务器程序上也碰到了错误链接 lua 引起的 bug ,在内部 maillist 上争论了好久。当时,作为 windows 程序员,跟同事中的 unix 程序员争论看似相同的问题时,却老说不到一起去;今天才发现,原来是相互之间对动态链接库的理解不同导致的。
今天,写下本文,或许可以让以后跨平台开发的朋友少走点弯路。
动态链接库在 unix 下,习惯以 .so 为文件名结尾(通常还以 lib 开头)。而 Windows 下是以 .DLL 为文件后缀。Windows 在处理 dll 上还有一些细节容易被人忽略,我曾经为这个写过一篇 Blog。
如果需要运行时主动加载一个动态链接库,windows 下可以使用 LoadLibrary 这个 kernel API (在 kernel32.dll 中);unix 下是用 dlopen 。Windows 下找到 dll 中导出符号的地址,可以用 GetProcAddress ,而 unix 也有对应的 api ...
这些相互对应的 api ,似乎预示着对等的功能,但事实上是有区别的。
DLL 事实上和 EXE 文件一样,同属 PE 格式的执行文件。对于隐式的引用外部符号,需要把外部符号所在的位置写在 PE 头上。PE 加载器将从 PE 头上找到依赖的符号表,并加载依赖的其它 DLL 文件。
但是,unix 上并非如此,so 文件大多为 elf 执行文件格式。当它们需要的外部符号,可以不写明这些符号所在的位置。也就是说,通常 so 文件本身并不知道它依赖的那些符号在哪些 so 里面。这些符号是由调用 dlopen 的进程运行时提供的。而 unix 下的执行文件本身会暴露自己静态链接的符号,(可以是自己本身实现的,或者是从静态库 .a 文件里链入的)。dlopen 将把这些符号通报给 dlopen 加载的 .so 文件,最终完成动态链接。(事实上 dlopen 还可以指定 mode ,完成更复杂的操作)
因为这个区别,unix 下的 lua 解释器可以完全静态链接所有的 lua api ;我们为 lua 扩展的库,以 so 的形式存在被运行时加载不会有任何隐患。而 Windows 下,必须生成一个 luacore 的 DLL 文件,由 lua 解释器于扩展库共享 lua api (还包括 crt 的实现) 才不会出问题。
也因为这个区别,VC 下才会有让 windows 开发新手困惑不解的动态链接 CRT ,静态链接 CRT ,多线程库,单线程库,等等的选项。没点点 windows 开发功力的人,多少都要在上面栽几个跟头。
从动态链接库的这个设计上来看,我个人感觉,Windows 弄的真是糟糕透顶。尤其是对开发者来说是这样。至少我们在 windows 下做一个 dll 文件给大家使用还需要携带一个 .lib 文件;而 unix 下一般只需要有相应的头文件就够了。对于编写新的 .so ,找不到的符号可以就让它在那里,直到最终执行文件来把所有需要的符号联合到一起。windows 可以存在一个 dll 对另一个 dll 的隐式依赖;而 unix 下一般不需要让 so 和 so 有隐式依赖关系。这让我们全局替换类似 CRT 的东西变的困难许多;而以我自己的编程经验来看,好处却没有多少。
顺便一提的是 unix 下需要用 ldconfig 来管理动态库,这比 windows 下 copy DLL 到当前目录下就可以用的方式,无疑提高了系统的安全性。
references:
http://stackoverflow.com/questions/2649334/difference-between-static-and-shared-libraries
http://stackoverflow.com/questions/9688200/difference-between-shared-objects-so-static-libraries-a-and-dlls-so
WIN下和LINUX动态库的区别的更多相关文章
- 静态库和动态库的区别和win平台和linux平台代码实现
静态库和动态库的区别 什么是库 库是写好的,现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说,库是一种可 ...
- iOS 静态库和动态库的区别&静态库的生成
linux中静态库和动态库的区别 一.不同 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 1. 静态函数库 这类库的名字一般是libxxx.a:利用静态函 ...
- 技巧:Linux 动态库与静态库制作及使用详解
技巧:Linux 动态库与静态库制作及使用详解 标准库的三种连接方式及静态库制作与使用方法 Linux 应用开发通常要考虑三个问题,即:1)在 Linux 应用程序开发过程中遇到过标准库链接在不同 L ...
- linux动态库加载RPATH, RUNPATH
摘自http://gotowqj.iteye.com/blog/1926771 linux动态库加载RPATH, RUNPATH 链接动态库 如何程序在连接时使用了共享库,就必须在运行的时候能够找到共 ...
- windows动态库与Linux动态库
Linux动态库和windows动态库的目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同.但是尽管有差异Linux动态库的windows动态库还是可以移植的,有一些规则以及经验是必须 ...
- linux动态库编译和使用详细剖析 - 后续
引言 - 也许是修行 很久以前写过关于动态库科普文章, 废话反正是说了好多. 核心就是在 linux 上面玩了一下 dlopen : ) linux动态库编译和使用详细剖析 - https://www ...
- VS中Debug和Realease、及静态库和动态库的区别整理(转)
原文出自:http://www.cnblogs.com/chensu/p/5632486.html 一.Debug和Realease区别产生的原因 Debug 通常称为调试版本,它包含调试信息,并且不 ...
- VS中Debug和Realease、及静态库和动态库的区别整理
一.Debug和Realease区别产生的原因 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使得程序在代码 ...
- linux动态库默认搜索路径设置的三种方法
众所周知, Linux 动态库的默认搜索路径是 /lib 和 /usr/lib .动态库被创建后,一般都复制到这两个目录中.当程序执行时需要某动态库, 并且该动态库还未加载到内存中,则系统会自动到这两 ...
随机推荐
- (转载):() { :|:& }; : # <-- 打开终端,输入这个,回车.你看到了什么??
代码::() { :|:& }; : 为什么这个东西会让你的系统死掉???有人执行了然后问我 让我们来分析一下这段代码,我改一下格式,但内容是一样的 代码::() # 定义一个叫“:”的过程 ...
- C/C++四种退出线程的方法
退出线程可以有四种方法: 1.线程函数的return返回(最好这样): 其中用线程函数的return返回, 而终止线程是最安全的, 在线程函数return返回后, 会清理函数内申请的类对象, 即调用这 ...
- softlayerFastUploadVHDtoBS
Object Storage Uploader Overview We’ve recently added the option to import customer-supplied Virtual ...
- Activity的onSaveInstanceState()和onRestoreInstanceState()方法
首先Android的Activity生命周期如下图: Activity的onSaveInstanceState()和onRestoreInstanceState()并不是生命周期方法,他们不同于onC ...
- 最小费用最大流模板 poj 2159 模板水题
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15944 Accepted: 8167 Descr ...
- Ajax长连接
所谓的长连接,就是不断去发送请求,把请求阻塞在服务器端,每次超过请求时间就去重新发送请求,保持连接,随时获取服务器端的响应的数据 项目案例: function connection(){ ...
- pyQt事件处理
Qt事件处理01 Qt处理事件的第二种方式:"重新实现QObject::event()函数",通过重新实现event()函数,可以在事件到达特定的事件处理器之前截获并处理他们.这种 ...
- 该如何关闭thinkphp的缓存呢?有下面几种方法可参考:
该如何关闭thinkphp的缓存呢?有下面几种方法可参考: (1)在配置文件中关闭缓存 在你的配置文件config.php文件中加上如下两句: 复制代码代码如下: 'TMPL_CACHE_ON' ...
- C#/.Net Post获取数据流的一种简单写法
最近在弄一些第三方的平台,经常调用第三方的接口实现某些特定的功能 在实现的同时基本上都需要本地的数据经过服务器在Request到第三方的服务器中处理,再返回相应的数据结构体:json/xml 以下是我 ...
- 使用repo的本地开发流程
repo下的本地开发流程 单分支开发: 1 本地新建工作目录并初始化repo库: repo init; 2 下载代码(只取服务器当前分支): repo sync -c; 3 创建本地 ...