Windows共享库的前生今世(一)

  “学会深入挖掘一些工具、技术和技艺...深入意味着要理解导致一种设计的推动力,而不仅仅是设计的细节...不只是鹦鹉学舌似的重复着从别人哪里听来的东西。”

  程序库在计算机技术的最早期就出现了,因为程序员意识到通过重用程序代码片段了一节省大量的时间和精力。

     共享库有两种:静态链接库(lib) 和动态链接库(dll)。

     我猜你肯定对他们不那么陌生,也许你有有时会遇到一大堆的莫名奇妙链接bug,google了好一阵,上面说修改你的链接选项/MD /MT,照做,ok done;也许你在LoadLibrary时会出总是返回NULL,于是google...;也许你在DllMain函数见鬼了,What the hell!,于是... 如果你只是想解决问题,请看这里这里。不过也许我们该花些时间真正去理解这些库的背后,也许它们没有想象中那么神秘。

    一个库就是一个绑定到我们的可执行程序的一个代码单元。一个dll是一个独立的的可执行代码单元,它在我们的程序运行时进行绑定。一个dll可以被多个应用程序使用,可以被多个进程加载,然而在内存中只有一份,就是多个进程使用内存中同一份dll(代码段、共享数据段)。

    使用dll有几个好处:

  1. 减少内存占用:尤其是对windows相关的库,如Kernel User GDI。在早期的Windows中OS就是有底层的MS-DOS和上层的Dynamic Link Libraries组成的。额外的dll层能够为所有的程序共享,不仅能保证OS在不到1M内存中运行,而且使各个程序互相协作,看下面...
  2. 根据需要在运行时加载/卸载库:一个很典型的例子Windows的绘图接口GDI,当我们使用一个打印机来绘图时,API调用被翻译成打印机的请求,这可以通过对特定的设备集合提供特定的编码来实现,但是MicroSoft选择了一种更为聪明的办法,GDI通过加载不同的代码实现不同输出设备的交互,这些代码就是所谓的设备驱动。这种概念就叫做动态链接,它是Windows的核心架构。
  3. 跨语言调用:因为dll本身就是可执行的文件(汇编指令集),因此可以被不同的语言共享。
  4. 方便升级:只要保证调用接口签名不变,我们可以使用不同的实现的dll替换已有的,这使得dll的升级非常方便。MicroSoft的COM架构使dll的这项优势发挥到了极致。COM只有五个永远不变接口,Windows的COM Server还封装了dll的加载卸载过程,让我们无需知道任何实现细节,无需知道它在哪,便可以进行调用。以后我会深入分析下COM的设计。

  不存在绝对好的技术,每个优点都会产生一些缺点,让我们看看dll的瑕疵:

  1. 拖慢程序加载速度:程序每次运行都需要动态链接和加载dll,会影响程序初始化顺序。
  2. The Well Known “DLL HELL:简而言之,dll的版本冲突、缺失、或注册错误(COM Server),造成程序无法正常运行。比如升级了dll库以适应新程序,但造成期望使用旧版本的程序无法正常运行。Microsoft为了减少DLL HELL的危害提出了Side-by-Side Assembly技术,又叫做WinSxS或者SxS,这项技术已经在VC++2005和VC++2008中得到应用。哦?也许你对VS项目中的manifest文件不会感到陌生,他就是记录dll版本的文件。

  动态库是在运行时与我们的代码进行绑定,而静态链接库是在链接时进行绑定。严格上说,在生成/链接阶段和其他的静态库和目标文件合并成可执行文件,或者在运行时被加载到可执行程序的静态内存地址(static memory offset),地址是在编译/链接期得到的。

  静态库没有动态库那么灵活,因为链接期已经将地址和数据绑定到程序中了,只有不改变依赖静态库的任何地址,才可以对库进行升级,否则需要重新连接所有程序。尽管动态链接更灵活,但要比静态链接慢很多,因为链接时做的大连工作在每次启动动态链接的程序是要重新做。使用静态库的可执行文件通常比使用动态链接的大一些,因为库的代码存储在可执行文件里,而不是另外的文件。静态链接时只包含了我们程序中直接或间接用到的那部分代码,然而动态链接需要加载整个库。

  

参考:

1. wikipedia

2. Linkers and loaders

3. 软件开发者路线图:从学徒到高手(中文版)

4. stackoverflow

转载请注明出处:http://www.cnblogs.com/hucn/archive/2011/04/15/2017469.html 

原文地址:https://www.cnblogs.com/hucn/p/the_shared_librarys_life_before_birth_1.html