向同名共享内存写入的数据大小不一样问题
来源:互联网 发布:软件合成系统 编辑:程序博客网 时间:2024/06/11 19:50
以同样的名字申请不同大小的共享内存中出现的问题
1、当我们使用CreateFileMapping时,我们告诉系统文件映射对象需要多大的物理存储器,此时会返回一个句柄给调用线程,这个句柄用来标识所创建的文件映射对象,
2、第二步我们需要使用MapViewOfFile.用来为文件的数据预订一块地址空间区域并将文件的数据作为物理存储器调拨给区域。将文件的数据映射到进程的地址空间
分析:首先我们一般会先创建一个共享内存的内核对象。Write之后然后用Read从共享中读取数据,在读取的时候我们会释放对象,也就是这个句柄,但是很不好意思,实际上,这个操作并不是我们想的这么美好,我们在open的时候会再返回一个句柄,尽管指的都是同一块内存,但是句柄的值是不一样的。当我们在read中读取之后并释放这个句柄的时候,只是我们open回来的句柄被我们关闭了,(当然我们会将句柄置为null)。所以其实在读取并关闭之后Create中创建的句柄还在。
于是我们想是不是可以在Write的函数中在打开的时候查看是不是存在,若是存在则关闭句柄。但是在open之后还会返回一个新的句柄值,尽管它们都指向的是同一块内存。
上面述说的事情,或许在每次都读取一样大小的数据是没有问题的,但是一旦我们向共享内存中写入的数据大小不一样的时候,应该说是更大的数据时候。通常我们创建之前会判断是否存在,然后关闭,再创建,可惜,这个再次创建的还是之前的,因为在内核对象中,若是对象的名字是一样的是不会再次创建的,而只是调用而已。于是这个内存的数据大小还是最初创建的1024个字节。现在我们要写入3000的数据,于是在memcpy中就会访问非法的地址。
这个问题整整困扰了我两天,我分析程序中每一个使用共享内存的地方,担心没有设置互斥。但是都正确,最后迫不得已使用了一个ProcessExplore的软件查看发现还有没有关闭的,现在问题发现了,那就好办了,直接的查找同名的,切记在读取数据中操作是达不到效果的,因为写与读会发生在两个不同的进程中,所以在写入数据的前面进行这一项的操作。
int WriteDataToMap(char *strMapName,int size,char *&buf){DWORD dwMapsize=18+size;for(int i=0;i<g_Maps&&i<200;i++){if(strcmp(strMapName,g_StrMap[i].nm)==0){CloseHandle(g_StrMap[i].hdl);memset(g_StrMap[i].nm,0,100);g_StrMap[i].hdl=NULL;g_Maps--;}}HANDLE hDbMap=OpenFileMapping(FILE_MAP_READ, FALSE, strMapName);if (GetLastError() == ERROR_ALREADY_EXISTS) {printf("文件%s已经存在.\n",strMapName);CloseHandle(hDbMap);hDbMap=NULL;}hDbMap=CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE , 0, dwMapsize, strMapName);if(hDbMap!=NULL) {if (GetLastError() == ERROR_ALREADY_EXISTS) {printf("文件%s已经存在.\n",strMapName);CloseHandle(hDbMap);hDbMap=NULL;return -2;}else{LPBYTE lpData = (LPBYTE)MapViewOfFile(hDbMap, FILE_MAP_WRITE, 0, 0, 0);if (lpData == NULL)//映射未成功{printf("文件映射失败");CloseHandle(hDbMap);hDbMap=NULL;return -1;}g_Maps++;memcpy(g_StrMap[g_Maps-1].nm,strMapName,100);g_StrMap[g_Maps-1].hdl=hDbMap;memset(lpData,0,dwMapsize);memcpy(lpData,&hDbMap,sizeof(HANDLE));memcpy(lpData+sizeof(HANDLE),&size,sizeof(int));memcpy(lpData+sizeof(int)+sizeof(HANDLE), buf,size );UnmapViewOfFile(lpData);}}return 1;}int ReadDataFromMap(char *pMapName,char *&lpbReceive){LPBYTE lpbReceiveBuf;int size=0;HANDLE hReceiveMap = OpenFileMappingA(FILE_MAP_READ, FALSE, pMapName); if (hReceiveMap!=NULL) { g_Maps++; g_StrMap[g_Maps-1].hdl=hReceiveMap; memcpy(g_StrMap[g_Maps-1].nm,pMapName,100); lpbReceiveBuf = (LPBYTE)MapViewOfFile(hReceiveMap,FILE_MAP_READ,0,0,0);//将内存区域映射到进程地址空间中 if (lpbReceiveBuf == NULL) { CloseHandle(hReceiveMap); hReceiveMap=NULL;//关闭内核对象,仅仅closeHandle是不够的,因为在进程句柄表中,这一项还是存在的,下次利用的时候 //不知道会是什么对象,它只是一个索引而已。tj理解 return -2; } HANDLE ldh; int n=0; memcpy(&ldh,lpbReceiveBuf+n,sizeof(HANDLE));//句柄 n+=sizeof(HANDLE); memcpy(&size,lpbReceiveBuf+n,sizeof(int));//长度 lpbReceive=new char[sizeof(int)+size+sizeof(HANDLE)];//分别为地址,长度 if(lpbReceive!=0) { if(size>0) memcpy(lpbReceive,lpbReceiveBuf+sizeof(HANDLE),sizeof(int)+size);//具体数据 } UnmapViewOfFile(lpbReceiveBuf); }return size;}
- 向同名共享内存写入的数据大小不一样问题
- 共享内存多次写入不同类型的数据测试代码
- java向csv写入html数据的问题
- JavaEE中向数据库写入数据乱码的问题
- php向mysql中写入中文数据的问题
- 向存在的文件中写入数据
- dom4j向xml文件写入数据自动生成xmlns=""属性的问题
- java程序向mysql写入数据乱码问题
- 共享内存的数据同步
- 如何向某一已知的内存地址写入某值
- 共享内存 —— 通过SharedPreferences实现进程间数据共享的问题详解
- 共享内存的权限问题
- 由JDBC事务引起的锁状态以及内存数据无法写入数据库的问题
- 向数据库写入500M的数据的方案
- 数据向Excel中写入的加速的办法.
- 添加的从web向数据库写入数据的模块
- 向oracle写入大数据
- java向文件写入数据
- 搜索——Ny 90 整数划分
- 古堡算式--爆破(蓝桥杯)
- 【ProjectEuler】ProjectEuler_053(对于1≤n≤100,C(n,r)有多少超过100万?)
- ubuntu笔记本数字及某些快捷键不能使用解决方法
- 【ProjectEuler】ProjectEuler_054(在扑克游戏中玩家1能赢多少局?)
- 向同名共享内存写入的数据大小不一样问题
- 关灯问题
- Nexus 4 解锁
- Android中NFC编程
- codeforces 171c
- Nexus 4 恢复出厂设置或刷原厂包
- codeforces 171c
- Nexus 4 Root
- STL容器之deque