以文本方式查看主题

-  曙海教育集团论坛  (http://sun4.cn/bbs/index.asp)
--  VB语言  (http://sun4.cn/bbs/list.asp?boardid=77)
----  技术讨论总结 -之- DLL和COM  (http://sun4.cn/bbs/dispbbs.asp?boardid=77&id=2609)

--  作者:wangxinxin
--  发布时间:2010-12-14 14:52:04
--  技术讨论总结 -之- DLL和COM
本周技术讨论会主要议题是DLL和COM

DLL是微软创造的二进制级别代码重用和应用程序管理的技术. DLL有如下这些好处:
1. 由于DLL动态加载的特性, 使得DLL模块和应用程序主干相剥离, 便于程序的升级 -----升级某个模块的功能只需覆盖某个DLL就可以了, 无需重新编译全部代码.
2. DLL的另一个好处也来自动态加载, 因此依赖于这个模块的其他各类应用程序不需与DLL编译在一起, 因此省出了更多的硬盘空间. 假如使用静态链接, 则每一个应用程序都需包含相应的模块镜像, 对磁盘的浪费是很严重的.
3. 更为重要的, 使用DLL还有助于节省内存. 因为系统为DLL提供了引用计数, 所有加载DLL的进程共享DLL的页面(当然数据不能共享,数据由进程自己保存.能够共享的是相当于代码段的页面),因此DLL使得内存的使用更有效.
4. 使用DLL可以实现多语言编程.例如VB的程序可以调用C++代码实现的DLL模块里面的函数.

DLL有两种加载方式, 一种是隐示加载, 就是在应用程序里包含DLL编写者提供的.h文件和编译时产生的.lib文件. 这样DLL将会在程序启动时加载入进程. 可以想见, 如word这类的程序在启动之时如此缓慢, 就是在不断的加载各种DLL模块.
另一种加载方式就是在程序中调用LoadLibrary函数显示加载DLL, 然后通过调用GetProcAddress函数获取相应函数的地址(即函数指针), 从而调用DLL内的函数. 这种做法有一个很好的优点就是不必所有的DLL都在启动时加载, 很多DLL模块都可以在需要使用的时候再临时加载, 有些DLL假如没有用到可以一直不加载. 我个人认为这是很好的用户体验. 我不理解的是为什么MS的各类产品没有使用这种方式进行程序设计.或许他已经用了, 但是启动时候必须加载的DLL项目太多?我就不再猜测了..
显示加载的DLL需要手动卸载, 调用FreeLibrary函数卸载它.

与普通的EXE一样, DLL也有一个进入点函数, 名字叫做DllMain, 这个函数接受三个参数, HINSTANCE hInst, DWORD fdwReason, PVOID fImpLoad
我在这里只讨论第二个参数fdwReason. 它可以是4个值: DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH
分别表示DLL首次加载,DLL从进程中释放, DLL线程的构造和终止. 其实系统为DLL提供了引用计数, DLL只加载入RAM一次, 所有进程共享DLL的各个页面, 所以只有第一次加载会调用带有DLL_PROCESS_ATTACH的DllMain. 但每次DLL从进程中释放都会调用带DLL_PROCESS_DETACH的DllMain, 这是因为进程保存了DLL里面的一些变量可能需要释放掉.
因此DllMain可以阻止进程结束.它可以在DLL_PROCESS_DETACH消息中放一个死循环,等待所有资源都被释放掉才退出. 如果有些资源出了问题, 就可能导致DLL无法正常退出.这就是为什么有些程序即使你去点小红叉叉也结束不了进程的原因.这种情况可以调用TerminateProcess函数强关进程.这就是为什么通过任务管理器仍然能结束进程的原因(但是这样做有可能丢失数据...)