我们都知道同一个应用程序的多个实例之间并不会影响各自的变量,虽然他们的地址空间都是被该应用程序的映像内的物理存储器所提交,他们的数据和代码都是指向了该应用程序的映像,但是他们还是不会影响各自的变量,因为采取了copy-on-write机制,当有一个实例去修改共享的那个数据区的时候,那么操作系统会另外分配一个内存块,该内存块就是存放这个实例修改的数据,所以并不会影响其他的应用程序实例。
那么可执行文件或dll的多个实例之间怎么去共享全局数据呢?现在进入我们的主题-----共享节
什么是共享节呢?
.exe和dll文件的映像都是由许多节组成的,比如:.text,.data,.bss它们都有自己的作用。存放为初始化的变量呀,存放未初始化的变量呀,存放代码呀等等。。这些东西我们都不用管,编译器会帮我们做好一切的。
我们也可以定义自己的共享节:
#pragma data_seg("Shared") int g_data=3; #pragma data_seg()
这里就定义了一个叫做:“Shared”的共享节,在该共享节中有一个初始化了的变量g_data,
注意:不要以为放在这里面就以为一定在这个共享节中,如果你没有初始化这个变量的话,那么这个变量还是放在默认的未初始化的共享节中。这样还不能达到我们共享变量的目的。我们还必须告诉链接程序,这个节里面的变量是要共享的。
/SECTION:Shared,RWS。这是在你的工程--设置---链接中配的。我们还可以在你的程序中直接设置:
#pragma comment(linker,"/section:Shared,rws")
这样就OK了。
下面我们来测试一下:
mydll.cpp:
#pragma data_seg("Shared") int g_data=3; #pragma data_seg() #pragma comment(linker,"/section:Shared,rws") //__declspec(allocate("Shared"))int g_data=3; extern "C" __declspec(dllexport) void setData(int temp) { g_data=temp; } extern "C" __declspec(dllexport) int getData() { return g_data; }
dllCallOne.cpp:
#include<iostream> #include<windows.h> using namespace std; extern "C" { typedef void (*PFN_setData)(int); typedef int (*PFN_getData)(); } void main() { HINSTANCE hinstance=LoadLibrary("D:\mydll.dll"); if(hinstance) { PFN_setData setData=(PFN_setData)::GetProcAddress( hinstance,"setData"); PFN_getData getData=(PFN_getData)::GetProcAddress( hinstance,"getData"); if(setData&&getData) { setData(4); getchar(); int temp=getData(); cout<<temp<<endl; } } }
dllCallTwo.cpp:
#include<iostream> #include<windows.h> using namespace std; extern "C" { typedef void (*PFN_setData)(int); typedef int (*PFN_getData)(); } void main() { HINSTANCE hinstance=LoadLibrary("D:\mydll.dll"); if(hinstance) { PFN_setData setData=(PFN_setData)::GetProcAddress( hinstance,"setData"); PFN_getData getData=(PFN_getData)::GetProcAddress( hinstance,"getData"); if(setData&&getData) { int result=getData(); cout<<result<<endl; getchar(); } } }
这样就实现了我们的多进程共享dll全局变量的目的了。
大家细心一点还会发现我在dll文件中注释了一行:
//__declspec(allocate("Shared"))int g_data=3;
这句话的意思就是:我就是要把这个变量放入到Shared共享节中。虽然它没有在那个节中定义,也不管这个变量有没有初始化。大家可以测试一下,把在共享节中的那个g_data删除,把这句话取消注释,同样也可以达到目的。