如何利用内存池和共享内存构建高速的进程间通信模型

先聊聊内存池吧,c++把内存管理的职责交给了我们,虽然给我们带来了很多麻烦,但是同样也给了我们很大的发挥空间,对于一个长期运行的系统来说,在一段时间后,堆的内存碎片会随着我们不断的申请和释放空间而越来越多,这就造成了我们的申请内存的消耗越来越大,对于这种问题,我们可以用内存池来解决。

       c++内存池的关键就在于重载new操作符,看一个简单的例子:

#ifndef __POOL_OBJECT_H__
#define __POOL_OBJECT_H__

class CMemPoolObject
{
protected:
    CMemPoolObject() = delete;
    CMemPoolObject(int a);
public:
    ~CMemPoolObject();
    void* operator new(size_t size);
    static CMemPoolObject* CreateInstance(int a);
    int getA();
    void setA(int a);
private:
    int a;
public:
    static char* mpCurrAddr;
};

#endif
#include 
#include 
#include "mempoolobject.h"

char* CMemPoolObject::mpCurrAddr = NULL;

CMemPoolObject::CMemPoolObject(int a)
{
    this->a = a;
}

CMemPoolObject::~CMemPoolObject()
{
    
}
void *CMemPoolObject::operator new(size_t size) {
    return (void*)mpCurrAddr;
}

int CMemPoolObject::getA()
{
    return a;
}

void CMemPoolObject::setA(int a)
{
    this->a = a;
}

CMemPoolObject* CMemPoolObject::CreateInstance(int a)
{
    return new CMemPoolObject(a);
}
//
//  main.cpp
//  Demo
//
//  Created by DGuco on 17/6/22.
//  Copyright © 2017年 DGuco. All rights reserved.
//

#include 
#include "mempoolobject.h"

#define MEM_SIZE  1024 * 10
int main(int argc, const char * argv[]) {
    static char acBuffre[MEM_SIZE] = {0};
    CMemPoolObject::mpCurrAddr = acBuffre;
    CMemPoolObject* object = CMemPoolObject::CreateInstance(1);
    std::cout << "a = %d" << object->getA() << std::endl;
    printf("&object %lld \n",object);
    printf("&acBuffre %lld \n",acBuffre);

}

#include "mempoolobject.h"

#define MEM_SIZE  1024 * 10
int main(int argc, const char * argv[]) {
    static char acBuffre[MEM_SIZE] = {0};
    CMemPoolObject::mpCurrAddr = acBuffre;
    CMemPoolObject* object = CMemPoolObject::CreateInstance(1);
    std::cout << "a = %d" << object->getA() << std::endl;
    printf("&object %lld \n",object);
    printf("&acBuffre %lld \n",acBuffre);

}

      通过重载new操作符我们就可以控制对象产生的方式和对象所在的位置,这里我们简单的把对象产生在事先申请好的静态存储区,这里有几点要注意,首先是析构函数,这里我什么都没做,因为内存在静态存储区,如果我们重载new操作符申请内存通过其他方式比如malloc等,注意要在析构函数中释放掉内存,或者重载delete操作符释放掉也可以。还有我们这里把构造函数生命成protect,是为了防止在栈上生成对象,因为此时不会调用new操作符,所以对象也不会生成在我们预期的地址上。这里只是简单的说下内存池的原理,具体的详细的实现推荐一篇文章吧,写的比我好:点击打开链接

    下面我们利用这个特性和共享内存。基于c++内存池,共享内存和信号量实现高速的进程间通信队列,支持单进程读单进程写,单进程多进程写,多进程读单进程写,多进程读多进程写。

  shmmqueue.h   shmmqueue.cpp  shm_rwlock.h  shm_rwlock.cpp
     基本原理是就是把消息管理类申请到开辟好的共享内存上,共享内存的大小要大于消息管理类自身的大小,剩余的部分用来放消息数据。内存上是一个环形的管理方式,内存池技术实现原理基于此篇文章:点击打开链接。 写的时候移动end索引,读的时候移动begin索引,保证了在单进程读和单进程写的时候是线程安全的,多进程读多进成写时利用信号量集(一个读信号和写信号)实现进程间的共享内存读写锁来保证多进程安全。

    更详细的内容介绍以及测试结果,见github地址:点击打开链接

 

 

     

      

 

 

       

       

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值