一、内存存储的好处
1、两个进程之间进行数据交换,一般可以通过文件或者数据库。使用文件或者数据库作为存取介质的,一般是对运行效率可能没有太高的要求。对于结构稍微复杂的数据使用文件存储似乎不是一个太好的选择,结构化存储格式诸如xml或者json是可以满足需求的。但是需要多线程读取文件的时候又需要手动去实现控制线程之间的同步,而数据库正是一种解决了多线程并发读写数据的产品。但是这并不意味数据库一定比文件好用,这仍然取决于具体的应用场景。就好像如果只是一个人搬家可能只需要一辆小车子,可是如果是公司搬家可能就需要几辆大货车或者更多大货车了。选择合适的存储介质可以在很大程度上避免资源的浪费。哲人说存在就是合理的,也许确实如此。而且现在很多数据库产品也都有使用内存存储的实现,比如mysql数据库的memory引擎、oracle数据库中的TimesTen,还有VoltDB。它们都很好的利用了内存相较于磁盘的绝对读写优势。但是由于内存的易失性和不可持久化,在对数据安全较高的场景下是不适合作为存储的对象,使用分布式内存数据库存储是否能逐渐解决这种问题呢。
2、由于内存的特性,决定了它更适合作为中间数据交换的媒介。不管是进程内多线程对共享数据的访问还是进程之间进行数据交换,使用内存访问都是一种高效的方式。由于进程的隔离,使得一个进程不能直接访问另一个进程的内存,虽然不能直接访问,但是可以间接访问。操作系统作为应用程序的宿主,能够实现对应用程序无限制无阻碍的数据访问。两个进程的数据交换如果比喻成现实中的交易行为,那么操作系统扮演的就是中间商的角色了。进程A向操作系统申请共享的虚拟内存访问,操作系统向进程A返回内核对象凭证。进程B通过这个内核对象凭证实现对虚拟内存的访问。
二、共享内存读写实现
1、读取端
// SharedMemoryReader.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int main()
{
//获取高精度运算时间,微妙
LARGE_INTEGER t1,t2,tc;
QueryPerformanceFrequency(&tc);
printf("Frequency: %u\n", tc.QuadPart);
QueryPerformanceCounter(&t1);
Sleep(1);
QueryPerformanceCounter(&t2);
printf("Begin Time: %u\n", t1.QuadPart);
printf("End Time: %u\n", t2.QuadPart);
printf("Lasting Time: %d\n", ((t2.QuadPart - t1.QuadPart) * 1000) / tc.QuadPart);
printf("Lasting Time: %u\n", (t2.QuadPart - t1.QuadPart) * 1000);
HANDLE hFileMapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, NULL,"chenpingping");
LPVOID pVoid = MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);
printf("hFileMapping=%d,pVoid=%s\n", hFileMapping,pVoid);
CloseHandle(hFileMapping);
}
2、写入端
// SharedMemory.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int main()
{
DWORD dwMaximumSizeHigh = 0, dwMaximumSizeLow = 256;
HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, dwMaximumSizeHigh, dwMaximumSizeLow, "chenpingping");
LPVOID pVoid = MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);
printf("hFileMapping=%d,pVoid=%d\n", hFileMapping, pVoid);
memset(pVoid,0,dwMaximumSizeLow);
BOOL bQuit = FALSE;
char line[256];
while(!bQuit){
printf("type: ");
char* str = fgets(line,256,stdin);
*(str + strlen(str) - 1) = '\0';
printf("you type【%s】\n",str);
if(str && (strcmp(str,"quit")== 0 || strcmp(str,"QUIT")) == 0){
bQuit = TRUE;
break;
}
else{
strcpy_s((char*)pVoid,strlen(str) + 1,str);
}
}
printf("application exit");
CloseHandle(hFileMapping);
UnmapViewOfFile(pVoid);
}
写入端运行结果
读取端运行结果
注意在调用 CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, dwMaximumSizeHigh, dwMaximumSizeLow, "chenpingping") 时需要注意函数 CreateFileMappingA的第一个参数。如果传的是 INVALID_HANDLE_VALUE,这时候使用的虚拟内存页面,否则可能使用的是磁盘页面。