构建一个共享内存的资源池,用于后续的使用
创建共享内存资源池的思路:
1、申请的内存由表头数据结构(相关统计信息)和节点数据结构组成
2、内存节点之间利用索引位置串联而成一个类似双向链表的数据结构
3、每次插入节点数据时,都从可用的头节点位置获取可用节点(freeheadpos),并从可用节点链表中去除节点数据
4、而当删除节点数据时,则将其添加到可用链表的头节点位置处
5、利用自定义索引字段来构建hash值,每个hash值对应一个map,用于保存具有同样hash值的节点。查找节点时,就先利用hash找到指定的map,再遍历map确认具体的节点
6、每个节点的数据结构利用“char node[1]”中的node来找到节点数据的指针位置,从而可读取数据值
// 每个节点的数据结构 struct MEMNODE { int prepos; // 前一个节点的位置索引,第一个指向0 int nextpos; // 后一个节点的位置索引,最后一个指向0 bool isfree; //是否被使用了 char node[1]; // 每个节点所存储数据的起始位置,node为起始位置的首地址 }; // 共享内存的表头信息 struct MEMHEAD { int freeheadpos; //空闲节点的头节点索引位置,用于后续从这个地方分配节点,且为连续的分配,表示第几个节点 int freecnt; //可用的空闲节点数目 int allcnt; // 所有的节点数目 int hashsize; // hash桶的大小 }; // NODE为所储存的数据结构,所以每个MEMNODE的大小为:(sizeof(MEMNODE) - 1 + sizeof(NODE)) template<typename INDEX, typename NODE> class Shm_Mapper { vector<map<INDEX, int> > Index_mapper_List; // 每个map存储一个hashvalue所对应的所有节点的索引及在内存中的位置。 MEMHEAD *pMemHead; void *pMapbeg; bool isopen; int ipckey; }; // 随着节点的申请和释放,将导致整个freeheadpos链表不再是连续的 // 通过freeheadpos变量可以找到第一个节点 int AllocNode(Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode) { memnode = NULL; if (pMemHead->freecnt <= 0) { return -1; } --(pMemHead->freecnt); memnode = Pos2Node(pMemHead->freeheadpos); pMemHead->freeheadpos = memnode->nextpos; //设置新的空闲首节点prepos为0 if (pMemHead->freeheadpos > 0) { MEMNODE* newhead = Pos2Node(pMemHead->freeheadpos); newhead->prepos = 0; } //将新获取的节点清空隔离 memnode->nextpos = 0; memnode->prepos = 0; memnode->isfree = false; return 0; } //将节点资源变为可用节点 FreeNode(Shm_Mapper<INDEX, NODE>::MEMNODE* memnode) { int curpos = Node2Pos(memnode); if (pMemHead->freeheadpos > 0) { MEMNODE* oldhead = Pos2Node(pMemHead->freeheadpos); oldhead->prepos = curpos; } memnode->nextpos = pMemHead->freeheadpos; memnode->prepos = 0; memnode->isfree = true; memset(memnode->node, 0, sizeof(NODE)); pMemHead->freeheadpos = curpos; ++(pMemHead->freecnt); return 0; } //通过索引来查询到指定的节点,只需要先利用index得到hashvalue,再将hashvalue作为索引由Index_mapper_List得到相应的map,最后利用index查找map得到节点的索引值,即可得到节点。 template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::Open(int ipckey, int nodecnt, int hashsize) { ipckey = ipckey; int memsize = sizeof(MEMHEAD) + MEMNODESIZE * nodecnt; int iShmID = 0; bool isfirst = false; if (ipckey == 0) { // 分配普通的内存 pMapbeg = new char[memsize]; if (NULL == pMapbeg) { return -1; } memset(pMapbeg, 0, memsize); pMemHead = (MEMHEAD*)pMapbeg; //得到表头的指针 }else{ //试图创建 if ((iShmID = shmget(ipckey, memsize, IPC_CREAT | IPC_EXCL | 0666)) < 0) { //若已经存在,则试图连接 if ((iShmID = shmget(ipckey, memsize, 0666)) < 0) { return -1; } } else { isfirst = true; } pMapbeg = shmat(iShmID, (const void*)NULL, 0); pMemHead = (MEMHEAD*)pMapbeg; } return InitMem(isfirst, nodecnt, hashsize); } //初始化共享内存的信息 template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::InitMem(bool isfirst, int nodecnt, int hashsize) { //首次创建,将贡献内存节点块全部放入空闲链表 if (isfirst) { pMemHead->freeheadpos = 1; pMemHead->freecnt = nodecnt; pMemHead->allcnt = nodecnt; pMemHead->hashsize = hashsize; for (int i = 0; i < pMemHead->hashsize; ++i) { Index_mapper_List.push_back(map<INDEX, int>()); } for (int i = 1; i <= pMemHead->allcnt; ++i) { MEMNODE* memnode = Pos2Node(i); memnode->isfree = true; memnode->prepos = i - 1; //尾节点 nextpos置为0 if (i == nodecnt) { memnode->nextpos = 0; } else { memnode->nextpos = i + 1; } memset(memnode->node, 0, sizeof(NODE)); } } else//非首次创建则读取共享内存索引 { for (int i = 0; i < pMemHead->hashsize; ++i) { Index_mapper_List.push_back(map<INDEX, int>()); } for (int i = 1; i <= pMemHead->allcnt; ++i) { MEMNODE *memnode = Pos2Node(i); //处理头节点 if (0 == memnode->prepos) { //空闲节点头节点 if (memnode->isfree == true) { if (pMemHead->freeheadpos != i) { return -1; } } else { if (InitMapList(memnode, i) < 0) { return -1; } } } } } isOpen = true; return 0; } //将memnode的索引及其节点的位置保存 template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::InitMapList(const MEMNODE* memnode, const int& curpos) { if (memnode->prepos != 0 || memnode->isfree == true) { return -1; } INDEX index; int hashvalue; Node2Index(*((NODE*)(memnode->node)), index); Index2Hash(index, hashvalue); if (hashvalue >= pMemHead->hashsize) { return -1; } map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue]; typename map<INDEX, int>::iterator iter = index_mapper.find(index); if (iter != index_mapper.end()) { return -1; } index_mapper.insert(typename map<INDEX, int>::value_type(index, curpos)); return 0; } template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::InsertNode(const NODE& node, Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode) { memnode = NULL; INDEX index; int hashvalue; Node2Index(node, index); Index2Hash(index, hashvalue); if (hashvalue >= pMemHead->hashsize) { return -1; } map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue]; typename map<INDEX, int>::iterator iter = index_mapper.find(index); //检查索引不存在,则创建 if (iter == index_mapper.end()) { if (AllocNode(memnode) < 0) { return -1; } memcpy(memnode->node, &node, sizeof(NODE)); int curpos = Node2Pos(memnode); index_mapper.insert(typename map<INDEX, int>::value_type(index, curpos)); } //检查索引存在则覆盖 else { int i = iter->second; if (i > 0) { memnode = Pos2Node(i); memcpy(memnode->node, &node, sizeof(NODE)); } //如果索引下面没有挂载数据,则重新申请 else { if (AllocNode(memnode) < 0) { return -1; } memcpy(memnode->node, &node, sizeof(NODE)); int curpos = Node2Pos(memnode); iter->second = curpos; } } return 0; } template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::QuerybyIndex(const INDEX &index, Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode) { memnode = NULL; int hashvalue; Index2Hash(index, hashvalue); if (hashvalue >= pMemHead->hashsize) { return -1; } map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue]; typename map<INDEX, int>::iterator iter = index_mapper.find(index); if (iter == index_mapper.end()) { return 0; } int i = iter->second; if (i == 0) { return -1; } else { memnode = Pos2Node(i); } return 0; } template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::DeleteNode(Shm_Mapper<INDEX, NODE>::MEMNODE* memnode) { if (memnode->isfree == true) { return 0; } int curpos = Node2Pos(memnode); //为索引首字段 if (memnode->prepos == 0) { INDEX index; int hashvalue; Node2Index(*((NODE *)memnode->node), index); Index2Hash(index, hashvalue); if (hashvalue >= pMemHead->hashsize) { return -1; } map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue]; typename map<INDEX, int>::iterator iter = index_mapper.find(index); if (iter == index_mapper.end()) { return -1; } if (curpos != iter->second) { return -1; } //设置新的空闲首节点prepos为0 if (memnode->nextpos > 0) { MEMNODE* newhead = Pos2Node(memnode->nextpos); newhead->prepos = 0; iter->second = memnode->nextpos; } else//只有一个节点直接删掉索引 { index_mapper.erase(iter); } } else { return -1; } //将新获取的节点清空隔离 memnode->nextpos = 0; memnode->prepos = 0; FreeNode(memnode); return 0; } struct stInfo { char[30] str; string data; } typedef char[30] stIndex; void Node2Index(const stInfo &node, stIndex &index) { index = node.str; } void Index2Hash(const stIndex &index, int &hashvalue) { hashvalue = 0; int len = index.strlen(); for (int i = 0; i < len; ++i) { hashvalue = ((unsigned char)index[i] + hashvalue) % pMemHead->hashsize; } } template<typename INDEX, typename NODE> typename Shm_Mapper<INDEX, NODE>::MEMNODE *Shm_Mapper<INDEX, NODE>::Pos2Node(const int& pos) { if (pos <= 0) { return (MEMNODE*)NULL; } else { return (MEMNODE*)((char *)_pMapbeg + sizeof(MEMHEAD) + MEMNODESIZE * (pos - 1)); } } template<typename INDEX, typename NODE> int Shm_Mapper<INDEX, NODE>::Node2Pos(const Shm_Mapper<INDEX, NODE>::MEMNODE* memnode) { if (memnode == NULL) { return 0; } else { return (int)(((char*)memnode - (char*)_pMapbeg - sizeof(MEMHEAD))/MEMNODESIZE + 1); } }