1. DLL
Windows 下的DLL 文件和EXE 文件实际上是一个概念,都是PE 格式的二进制文件。
利用DLL 实现共享数据
在一个DLL 中需要进程间共享的变量分离出来,放到另外一个数据段中,然后将这个数据段设置成进程间可以共享的, 一个DLL 中有两个数据段,一个是用于进程共享的,另外一个是用于私有的。
导出符号: __declspec(dllexport)
最终链接时,我们必须把与DLL 一起产生的lib, 与 .obj 文件链接, 这个lib 里面不是真正包含代码和数据,而是用来描述dll 的导出符号和一些” 桩” 代码,以前一直认为最终链接的时候是dll 与.obj 做链接,看来还是与.lib 做链接比较正常。
LoadLibrary ,装载DLL 到进程的地址空间,
GetProcAddress, 查找某个符号,
FreeLibrary 释放DLL 。
2. 符号导出导入表
所有函数名是按照ASCII 顺序排序的,以便于动态链接器查找函数名字时可以速度更快(2 分查找)
导出表的查找过程:
先利用函数名去查找相应的序号, 然后通过序号去查找地址。
Windows 修改导入表里面ITA 的序号变为真实地址的做法是
在装载时,将导入表所在的位置的页面修改成读写的,一旦导入表的ITA 被改写完毕,再将这些页面设回至只读属性。
3. DLL 优化
Rebasing
跟ELF PIC( 代码无关) 相比,DLL 的rebasing 相当简单,只是简单rebase 了加载的DLL 的基地址( 如果这个DLL 的基地址被占用( 一般的DLL 加载的基地址是0X1000000)). 所以速度肯定比上ELF 的PIC,GOT 这样的方案,内存消耗也很多,在进程共享上也无法与ELF 相比。
4. C++ 与动态链接
不用C++ 写共享库的原因:1.C++ 无ABI 级别的规定,至规定了语言层面的规定,
2.C 与C++ 之间如何相互操作(extern”C”)
Com 本质论 那个例子很生动。
从Windows XP 开始, Application 有Manifest 这个东西,用于控制Application 需要加载的DLL ,一般是系统的DLL 。