WIN32汇编语言教程:第11章 动态链接库和钩子 · 11.1 动态链接库(6)
11.1.4 动态链接库中的数据共享
当多个应用程序同时使用同一个动态链接库的时候,这些动态链接库在系统中是存在于不同进程的地址空间中的,它们代表“宿主”程序工作,互相之间没有任何联系。这一点可以通过一个简单的实验来演示:当我们多次运行UseDll1.exe(或UseDll2.exe),按动不同对话框中的“增加”或“减少”按钮的时候,每个对话框中的计数值按照自己的规律增减,不会受到其他对话框中计数值的影响。这就是说,虽然Counter.dll被多个进程同时装入,但是操作系统为它们映射了各不相同的数据段,使它们工作起来互不影响。
但是需要在进程间进行数据共享的时候,这种互相隔离的特征就不是我们所需要的了,当然,解决的方法之一就是使用第10章中介绍的内存映射文件,但是更简单的办法是通过构造特殊的动态链接库来实现。
再次以前面的Counter.dll为例,现在将它的计数器改成是全局的,也就是说运行UseDll1.exe的多个拷贝的时候,不同对话框增减的是同一个计数器。
回顾第02章对Link.exe程序的介绍,会发现链接器有一个/SECTION选项,可以将某个节区的属性自行定义,选项中有一个S属性,代表将节区的属性设置为共享,这就是我们需要的,实际上不必修改Counter.asm源程序,只需要把Makefile文件中的Link选项修改一下:
DLL = Counter ML_FLAG = /c /coff LINK_FLAG = /subsystem:windows /Dll /section:.bss,S $(DLL).dll: $(DLL).obj $(DLL).def Link $(LINK_FLAG) /Def:$(DLL).def $(DLL).obj .asm.obj: ml $(ML_FLAG) $< .rc.res: rc $<
未初始化数据段 .data?的节区名称为 .bbs,加上/section:.bss,S选项就可以将这个段的属性改为共享,这样,当DLL被不同应用程序装载的时候,不但映射到不同进程地址空间中的代码段来自同一段物理内存,.data?段的映射也来自同一段物理内存。
修改Makefile以后来验证一下,使用nmake /a将DLL重新编译并将Counter.dll文件拷贝到UseDll1程序所在目录,然后多次执行UseDll1程序以产生多个对话框,当在一个对话框中按下“增加”按钮将计数增加到x的时候,再换到另一个对话框中再按“增加”按钮,会发现出现的值是x+1而不是原来应该出现的1,表示这些对话框操作的是一个共享的计数器。
如果不希望全部的数据都共享,如hInstance等私有的数据,可以把这些数据放在初始化数据段 .data中,它的节区名称不同于 .data?段,在将 .data?段的属性修改为共享的时候并不会影响 .data段的属性。
上页:第11章 动态链接库和钩子 · 11.1 动态链接库(5) 下页:第11章 动态链接库和钩子 · 11.2 Windows钩子(1)