DLL入门浅析(5)——使用DLL在进程间共享数据
http://www.cppblog.com/suiaiguo/archive/2009/07/21/90734.html
在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的,因为所有的进程用的都收同一块地址空间;而在Win32环境中,情况却发生了变 化,每个进程都有了它自己的地址空间,DLL函数中的代码所创建的任何对象(包括变量)都归调用它的进程所有。当进程在载入DLL时,操作系统自动把 DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。(在物理内存中,多进程载入DLL 时,DLL的代码段实际上是只加载了一次,只是将物理地址映射到了各个调用它的进程的虚拟地址空间中,而全局数据会在每个进程都分别加载)。也就是说每个 进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。
因此,在Win32环境下要想在多个进程中 共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置 在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。
在DLL的实现文件中添加下列代码:
int SharedData = 123; // 必须在定义的同时进行初始化!!!!
#pragma data_seg()
在#pragma data_seg("DLLSharedSection")和#pragma data_seg()之间的所有变量将被访问该Dll的所有进程看到和共享。仅定义一个数据段还不能达到共享数据的目的,还要告诉编译器该段的属性,有三 种方法可以实现该目的(其效果是相同的),一种方法是在.DEF文件中加入如下语句:
DLLSharedSection READ WRITE SHARED
另一种方法是在项目设置的链接选项(Project Setting --〉Link)中加入如下语句:
还有一种就是使用指令:
那么这个数据节中的数据可以在所有DLL的实例之间共享了。所有对这些数据的操作都针对同一个实例的,而不是在每个进程的地址空间中都有一份。
当进程隐式或显式调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址空间里。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈。
下面来谈一下在具体使用共享数据段时需要注意的一些问题:
· 所有在共享数据段中的变量,只有在数据段中经过了初始化之后,才会是进程间共享的。如果没有初始化,那么进程间访问该变量则是未定义的。
· 所有的共享变量都要放置在共享数据段中。如何定义很大的数组,那么也会导致很大的DLL。
· 不要在共享数据段中存放进程相关的信息。Win32中大多数的数据结构和值(比如HANDLE)只在特定的进程上下文中才是有效地。
· 每个进程都有它自己的地址空间。因此不要在共享数据段中共享指针,指针指向的地址在不同的地址空间中是不一样的。
· DLL在每个进程中是被映射在不同的虚拟地址空间中的,因此函数指针也是不安全的。
当然还有其它的方法来进行进程间的数据共享,比如文件内存映射等,这就涉及到通用的进程间通信了,这里就不多讲了。
相关推荐
http://topic.csdn.net/u/20100901/22/10bb727c-711f-4ae4-a318-006206e00a27.html?41231
如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,像dll中的全局变量这种东西是会被每个进程复制一份的)。 2) 不需编译的软件系统升级,若一个软件系统使用了dll,则该dll被改变...
如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,像dll中的全局变量这种东西是会被每个进程复制一份的)。 2) 不需编译的软件系统升级,若一个软件系统使用了dll,则该dll被改变...
如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,像dll中的全局变量这种东西是会被每个进程复制一份的)。 2) 不需编译的软件系统升级,若一个软件系统使用了dll,则该dll被改变...
对于全局变量的使用C和C++没有什么不同,所以我们把焦点集中在全局函数上(此外全局变量的规则一样)。 我们知道C++程序要使用C语言的函数就必须在函数声明前加上extern "C"关键字,这对于静态库和DLL没有什么不同...
第三步的动作,不要在回调或者线程中调用,请用变量的办法如内存共享,全局变量,发消息等方式。 按住Shift键点鼠标可显示该点xyz的值; 按住shift并拖动鼠标,可实现画面移动; 直接拖动鼠标实现画面旋转。
本示例详细列举了关于dll的各类使用,包括dll的动态链接和静态链接、dll的用def和不用def、dll全局变量、函数以及类封装,最后也为VB开发人员附上了dll的调用示例,还有就是我关于dll的心得,希望能为dll入门的人员...
' 加强"全局共享类"中,"写共享"增加可空参数一个,可指定写入数据的长度 ' 增加"全局共享类"中,"写共享文本" ' 增加"全局共享类"中,"写共享数值" ' 增加"全局共享类"中,"读共享文本" ' 增加"全局共享类"中,"读共享...
进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点...
第142页 5.3.2 全局变量 第145页 5.3.3 共享变量 第146页 5.4 综合实例:等差序列求和 第147页 5.5 思考与练习 第148页 第6章 外部程序接口与扩展 第148页 6.1 dll调用 第152页 6.2 windows api调用 第156页 6.3 可...
一般静态库、动态库的创建和使用 (非 MFC 动态库) 总结解决方案的学习内容: 1.静态库的创建和使用 2.动态函数库的创建及使用 3.动态库的动态调用和静态调用 4.动态库导入、出全局共享变量 5.动态库导入、出类
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增...
2.11.3 全局变量 77 2.11.4 静态变量 80 2.12 名称空间 80 2.12.1 声明名称空间 81 2.12.2 多个名称空间 82 2.13 c++/cli编程 84 2.13.1 c++/cli特有的基本数据类型 84 2.13.2 命令行上的c++/cli输出 87 ...