Win32环境下动态链接库(DLL)编程原理
比较大的应用程序都由很多的模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作。其中可能存在一些模块的功能比较通用,在构造其他软件系统的时候仍然会被使用。
在构造软件系统时,如果将所有模块的源代码都静态编译到整个应用程序EXE文件当中,会产生一些问题:一个缺点是增加了应用程序的大小,它会占用更多的磁盘空间,程序运行时也会消耗比较大的内存空间,造成系统资源的浪费。
另一个缺点是,在编写大的EXE程序时,每次修改重建时都必须重新编译所有的源代码,增加了编译过程的复杂性,也不利于阶段性的单元测试。
Window系统平台提供了一种完全不同的较为有效的编程和运行环境,你可以将独立的程序模块创建成较小的DLL文件,并可以对它们单独编译和测试。
在运行时,只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间当中。这种方法不仅减少了EXE文件的大小和内存空间的需求,而且使这些DLL模块可以同时被多个应用程序使用。
Microsoft Windows 自己就将一些主要的系统功能以DLL模块的形式实现。
一般来说,DLL是一种磁盘文件,带有DLL扩展名,它是由全局数据、服务函数和资源组成的,在运行时被系统加载到进程的虚拟空间当中,称为调用进程的一部分。
如果与其它DLL之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上面。DLL模块中包含各种导出函数,用于向外界提供服务。
Windows在加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配。
在Wind32环境中,每个进程都复制了自己的读/写全局变量。如果想要与其他进程共享内存,必须使用内存映射文件或者声明一个共享数据段。
DLL模块需要的堆栈内存都是从运行进程中的堆栈中分配出来的。
DLL现在已经很容易编写了。Win32大大简化了其编程模式,并有许多来自AppWizard和MFC类库的支持。
导入和导出函数的匹配
DLL文件中包含一个导出函数表。这些导出函数由它们的符号名和称为表示号的整数与外界联系起来。函数表中还包含了DLL中函数的地址。当应用程序加载DLL模块时,它并不知道调用函数的实际地址,但是它知道函数的符号名和标识号。
<