文章来源:http://blog.csdn.net/huanglong8/article/details/53771024
在上一章中,我们使用最简单的内存共享技术data_seg,在实际的开发中,为了便于管理和维护,通常猿猴们会把它放到外面去,也就是动态库中,在动态库中提供必要的接口,使加载它到进程空间中时,得意访问其共享资源。
注意的事在强调,data_seg在没有任何进程加载时,则会被释放,所以在开发过程中需要额外注意。
由于这种机制,导致的数据改变是不会被通知到的,当一个程序修改变量后,需要另外一个程序主动读取才能获取共享数据结构。当多个程序同时修改时,就需要给变量上锁,此部分是多线程的问题,也比较简单,这里就不说了。
定义共享内存数据
#pragma data_seg("HL_IPC_DLLDLL")
unsigned int flag = 0;//这里任何变量都必须初始化,否则将在数据段以外,无法共享
#pragma data_seg()
//flag = 0 表示无数据改变
//flag = 1 表示A改变了数据
//flag = 2 表示B改变了数据
__declspec(allocate("HL_IPC_DLLDLL")) char g_HL_IPC_DLLDLL[0xFFF] = {0};
#pragma comment(linker, "/Section:HL_IPC_DLLDLL,RWS")
#define INTERVAL 100 //写入读取的间隔时间,为了防止丢数据
定义读写变量的接口
EXPORT void SetDllString(char dst,char* str)
{
Sleep(INTERVAL);
strcpy(g_HL_IPC_DLLDLL,str);
if(dst == 'A') flag = 1;
if(dst == 'B') flag = 2;
}
EXPORT void GetDllString(char* str)
{
if(str == 0) return;
strcpy(str,g_HL_IPC_DLLDLL);
}
EXPORT void WaitGetDllString(char dst,char* str)
{
while(1)
{
if( (flag == 1 && dst == 'A') ||
(flag == 2 && dst == 'B'))
{
GetDllString(str);
break;
}
else Sleep(INTERVAL);
}
flag = 0;
}
虽然这种办法很蠢,但这里也只是为了完成这个小需求,没有考虑更多更好的方法。不喜欢的就不要喷我了。
在头文件中对接口函数导出进行定义
#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif
EXPORT void SetDllString(char dst,char* str);
EXPORT void GetDllString(char* str);
EXPORT void WaitGetDllString(char dst,char* str);
编译成DLL库即可,我们也采用显式动态加载,唉,写C写多了,就成这了,延迟加载还是不错的,大家也可以用,具体设置VS,大家参考百度吧。
控制台A的IO线程
DWORD WINAPI Send(LPVOID lpParameter )
{
char buff[0xFFF];
ZeroMemory(buff,sizeof(buff));
while(true)
{
gets_s(buff,sizeof(buff));
SetDllString('A',buff);
}
return 0;
}
DWORD WINAPI Recv(LPVOID lpParameter )
{
char buff[0xFFF];
ZeroMemory(buff,sizeof(buff));
while(1)
{
WaitGetDllString('B',buff);
printf("From B data: %s\n",buff);
}
return 0;
}
进入main函数后初始化两个线程,一个用来读,一个用来写,同样在控制台B中也是这样,以此来完成AB两个进程的用户输入信息交互。
完整示例代码:
[下载] Windows进程通信_共享内存
这是最简单的共享内存了,用起来也比较简单,但是在实际开发的工程中,尤其是关于多进程多线程时,一定要做好同步互斥的工作。