DLL的那些事儿

DLL的那些事儿

       DLL是dynamic-Link Library的缩写,它一直是windows编程的基石。DLL是一个windows程序员必须要掌握的技能。下面从几个不同的方面介绍一下DLL的基础知识,或许会有不妥的地方,希望大家指正。
一、DLL与EXE的区别。
1.在进程初始化时,系统在进程的地址空间中创建一个堆。这个堆就是进程的默认堆。而DLL中没有与其相关的堆。
2.每当创建一个线程时,系统就会为线程(每个线程都有自己的栈)保留一个栈空间区域(在进程的地址空间),并将物理存储器提交给这个保留的区域。而DLL中没有与其相关的栈空间。
3.一旦DLL的文件映射到调用进程的地址空间,则DLL几乎失去了它作为DLL的所有特征标志,对于进程中的线程而言,DLL的代码和数据看起来就像是恰好存在于进程地址空间中的额外代码和数据。被DLL中的函数代码多创建的任何对象都属于调用它的线程(一个DLL并不拥有任何元素包括栈和堆)。当然有一条需要特别注意,就是在DLL中申请的heap应当有DLL释放这个空间,否则会带来灾难性后果,这个不能说明DLL中有堆空间,而是由于DLL链接的runtime library导致的。
4.如果DLL文件被多个进程共享,通过copy-on-write机制来实现。
5.当然作为可执行模块,DLL必需含有二进制代码和全局/静态数据变量。只是DLL不能单独执行只能依附于进程执行,即必需加载到进程的地址空间中的,自己没有单独的地址空间,这个是所有区别的缘由所在。
二、Dll的加载。
   为了使用DLL模块中的函数,DLL必需映射到进程地址空间,有两种方法:
1)隐式装载时链接, 这需要链接时链接那些函数所在DLL的导入库lib文件,lib向系统提供了载入DLL时所需的信息及DLL函数定位。
2)显式运行时链接, 运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免使用lib导入库文件。
三、dll优点。
1)减少内存占用:当多个应用程序调用同一个Dll时,在物理上只保留一份内存,通过copy-on-write原则共享。尤其是对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的升级非常方便。
四、关于DllMain函数。
1)DLL_PROCESS_ATTACH调用,在创建主线程后会调用,一般用来初始化自己,在该调用中,应当避免调用从其他Dll中导入的函数,避免调用loadLibrary等函数。
2)DLL_THREAD_ATTACH调用,在进程中创建一个线程时,系统将检查当前映射到进程地址空间的所有DLL的文件映射,并以DLL_THREAD_ATTACH为参数调用每个DLL的DllMain函数。

参考文献:
1.windows核心编程
2.msdn

你可能感兴趣的:(DLL的那些事儿)