📄 cmbuf.cpp
字号:
//CMBUF_CPP
#include "CMBuf.h"
//constructor
CMemCtrl::CMemCtrl(unsigned long num,unsigned long extnum){
m_bufptr=new mbufs[num]; //申请NUM个mbuf块
bufptr=new MemMTable[num]; //内存管理表
extdatptr= new ExtBlock[extnum]; //申请簇块extnum个
exttableptr= new ExtTable[extnum]; //簇管理表
//内存管理表初始化
for(int i=0;i<num-1;i++)
{
bufptr[i].m_buf=&m_bufptr[i];
bufptr[i].next=&bufptr[i+1];
}
bufptr[num-1].m_buf=&m_bufptr[num-1];
bufptr[num-1].next=0;
bufHeadptr=&bufptr[0];
bufEndptr=&bufptr[num-1];
//簇管理表初始化
for(i=0;i<extnum-1;i++)
{
exttableptr[i].extdatptr=&extdatptr[i];
exttableptr[i].next=&exttableptr[i+1];
}
exttableptr[extnum-1].extdatptr=&extdatptr[extnum-1];
exttableptr[extnum-1].next=0;
m_extbufhptr=&exttableptr[0];
m_extbufeptr=&exttableptr[num-1];
//空闲内存管理表队列初始化
freeHeadptr=freeEndptr=0;
//空闲簇管理表队列初始化
m_extfreehptr=0;
m_extfreeeptr=0;
//建立所需信号量
mbufQueSemmutex=semMCreate(SEM_INVERSION_SAFE); //建立拥有优先级翻转保护的信号量
freemtQueSemmutex=semMCreate(SEM_INVERSION_SAFE);
extQueSemmutex=semMCreate(SEM_INVERSION_SAFE);
freeextmtQueSemmutex=semMCreate(SEM_INVERSION_SAFE);
}
//destructor
CMemCtrl::~CMemCtrl()
{
delete[] m_bufptr;
delete[] bufptr;
delete[] extdatptr;
delete[] exttableptr;
/* 没有释放信号量 */
}
CMemCtrl *Cmbuf=new CMemCtrl(1024,1024);
//********************************************
// 从内存管理区分配一个mbuf供使用
//
//输入:mbuf用于的数据类型描述
//输出:成功返回一个mbuf地址供使用,失败返回0
//********************************************
mbufs *CMemCtrl::AllocMbuf(unsigned short type)
{
mbufs* tempmbuf;
MemMTable* temptable;
int ret;
if(!bufHeadptr->next)
{
printf("没有可用动态内存空间分配 \n");
return MRTNNULL;
}
else
{
tempmbuf=bufHeadptr->m_buf;
tempmbuf->m_types=type;
temptable=bufHeadptr;
bufHeadptr=bufHeadptr->next;
temptable->next=0;
ret=PushMemtable(temptable);
if(ret)
{
printf("mbuf管理表释放失败 \n");
}
}
return tempmbuf;
}
//******************************************
// 释放一个使用中的mbuf
//
//输入:需要释放的mbuf地址
//输出:成功返回0 ,失败返回1
//******************************************
bool CMemCtrl::FreeMbuf(mbufs *usebuf)
{
if(!usebuf)
{
printf("FreeMbuf 猪啊你,你在释放一个0地址的mbuf \n");
return MRTNFALSE;
}
MemMTable *temptable;
mbufs *tempbuf,*tempbuf2;
S32 num=0;
do
{
if(!num)
{
tempbuf=usebuf;
}
else
{
tempbuf=tempbuf2;
}
tempbuf2=tempbuf->m_nexts;
//memset(tempbuf,0,sizeof(tempbuf));//释放后清0
num++;
temptable=PopMemtable();
temptable->m_buf=tempbuf;
//把释放的mbuf入空闲buf管理表中
bufEndptr->next=temptable;
temptable->next=0;
bufEndptr=bufEndptr->next;
//需要释放簇
if(tempbuf->m_flagss == 2 or tempbuf->m_flagss == 3)
{
FreeMcl((ExtBlock *)tempbuf->m_exts.extbuf);
}
tempbuf->m_exts.ext_size=0;
memset(&tempbuf->m_hdr,0,20); //把头部清0 固定为20字节
}while(tempbuf2);
usebuf=0;
return MRTNTRUE;
}
//*******************************************
// 申请一个簇供使用
//
//输入:无
//输出:成功返回一个可用簇地址,失败返回空指针
//*******************************************
ExtBlock *CMemCtrl::AllocMcl()
{
ExtBlock *tempextb;
ExtTable *tempexttable;
S32 ret;
if(!m_extbufhptr->next)
{
printf("没有可用簇空间分配 \n");
return MRTNNULL;
}
else
{
tempextb=m_extbufhptr->extdatptr;
tempexttable=m_extbufhptr;
m_extbufhptr=m_extbufhptr->next;
//将这个管理表放入空闲管理表队列中
ret=PushExttable(tempexttable);
if(ret)
{
printf("CMBuf.cpp AllocMcl 空闲簇管理表释放失败 \n");
}
}
return tempextb;
}
//******************************************
// 释放一个使用中的簇
//
//输入:使用中的簇地址
//输出:成功返回0 失败返回1
//******************************************
bool CMemCtrl::FreeMcl(ExtBlock *usemcl)
{
if(!usemcl)
{
printf("释放簇失败,簇指针为空 \n");
return MRTNFALSE;
}
if(!m_extbufhptr)
{
printf("释放簇失败,没有新的簇表供使用 \n");
return MRTNFALSE;
}
ExtTable *temptable;
//从空闲簇管理表队列中取出一个簇管理表
temptable=PopExttable();
if(!temptable)
{
printf("CMBuf.cpp FreeMcl 取出空闲簇管理表失败 \n");
return MRTNFALSE;
}
else
{
temptable->extdatptr=usemcl;
m_extbufeptr->next=temptable; //放入空闲簇管理队尾的next
m_extbufeptr=m_extbufeptr->next; //空闲簇管理队尾后移
}
return MRTNTRUE;
}
//***************************************************
// 向一个mbuf中拷贝数据
//
//功能:往一个mbuf中拷贝数据
//输入:目标mbuf的地址,要拷贝数据,长度
//输出:成功返回0,失败返回1
//***************************************************
bool CMemCtrl::AddData(mbufs *mbufs,char *data,int len)
{
if(!mbufs)
{
cerr<<"AddData The input ptr is a Zero Address"<<endl;
return MRTNFALSE;
}
if(len<=MINCLSIZE) //如果长度小于等于208,则申请一个mbuf来装载这个
{
if( len >= MLEN) //需要两个mbuf够成的分组来存放
{
mbufs->m_flagss=PTKDHR;
mbufs->m_leng=MHLEN;
mbufs->m_pkthdrs.len=len; //整个分组总长度
mbufs->m_pkthdrs.rcvif=0; //NULL
mbufs->m_datas=mbufs->m_pktdat;
memcpy(mbufs->m_pktdat,data,MHLEN);
class mbufs *tempbuf;
tempbuf=AllocMbuf(mbufs->m_types);
mbufs->m_nexts=tempbuf;
tempbuf->m_nexts=0;
tempbuf->m_flagss=NOMAL;
tempbuf->m_leng=len-MHLEN;
tempbuf->m_datas=tempbuf->m_dat;
memcpy(tempbuf->m_datas,data+MHLEN,len-MHLEN);
}
else //一个mbuf就可以独立存放
{
mbufs->m_nexts=0;
mbufs->m_nextpkts=0;
mbufs->m_flagss=NOMAL;
mbufs->m_leng=len;
mbufs->m_datas=mbufs->m_dat;
memcpy(mbufs->m_dat,data,len);
}
}
else //len>208的情况,需要分配簇来存放额外数据
{
ExtBlock *tempMcl;
if(len<=MCLBYTES)
{
mbufs->m_nexts=0;
mbufs->m_nextpkts=0;
mbufs->m_flagss=EXT;
mbufs->m_leng=len;
tempMcl=AllocMcl();
if(!tempMcl)
{
FreeMbuf(mbufs);
return MRTNFALSE;
}
else
{
mbufs->m_exts.extbuf=tempMcl->extDat;
}
mbufs->m_datas=mbufs->m_exts.extbuf;
mbufs->m_exts.ext_free=0;
mbufs->m_exts.ext_size=MCLBYTES;
memcpy(mbufs->m_datas,data,len);
}
else
{
//完成第一个mbuf的数据装填
mbufs->m_nextpkts=0;
mbufs->m_flagss=PTKDHREXT;
mbufs->m_leng=MCLBYTES;
mbufs->m_datas=mbufs->m_exts.extbuf;
mbufs->m_pkthdrs.len=len; //整个分组总长度
mbufs->m_pkthdrs.rcvif=0; //NULL
tempMcl=AllocMcl();
if(!tempMcl)
{
FreeMbuf(mbufs);
return MRTNFALSE;
}
else
{
mbufs->m_exts.extbuf=tempMcl->extDat;
}
mbufs->m_exts.ext_free=0;
mbufs->m_exts.ext_size=MCLBYTES;
memcpy(mbufs->m_datas,data,MCLBYTES);
//叠代,把剩下的数据装填完
class mbufs *tempbufext;
bool ret;
tempbufext=AllocMbuf(mbufs->m_types);
ret=AddData(tempbufext,data+MCLBYTES,len-MCLBYTES);
if(!ret)
{
FreeMbuf(mbufs);
return MRTNFALSE;
}
mbufs->m_nexts=tempbufext;
}
}
return MRTNTRUE;
}
//***************************************************
// 从一个mbuf中取出数据
//
//功能:从一个mbuf中拷贝数据到一个连续缓冲区中(取出数据并没有删除该mbuf)
//输入:源mbuf的地址,目的缓冲区地址,目的缓冲区大小
//输出:成功返回取出数据长度值,失败返回0
//***************************************************
S32 CMemCtrl::GetData(mbufs *usebuf,char *destbuf,int desbufsize)
{
mbufs *tempbuf=0;
S32 num=0; //返回的长度
//int templen=0;
switch(usebuf->m_flagss)
{
case NOMAL:
case EXT:
if(desbufsize < usebuf->m_leng)
{
printf("CMemCtrl::GetData NOMAL 接收缓冲区太小 \n");
return 0;
}
memcpy(destbuf,usebuf->m_datas,usebuf->m_leng);
num=usebuf->m_leng;
break;
case PTKDHR:
case PTKDHREXT:
if(desbufsize < usebuf->m_pkthdrs.len)
{
printf("CMemCtrl::GetData PTKDHR 接收缓冲区太小 \n");
return 0;
}
//只要next不为空则取出数据到连续缓冲区
tempbuf=usebuf;
num=0;
while(1)
{
memcpy(destbuf+num,tempbuf->m_datas,tempbuf->m_leng);
num += tempbuf->m_leng;
if(tempbuf->m_nexts)
{
tempbuf=tempbuf -> m_nexts;
}
else
{
break;
}
}
break;
default:
printf("CMemCtrl::GetData mbuf flags 为错误值 \n");
return 0;
break;
}
return num;
}
//***********************************************
// 前向链接
//功能:将一个mbuf链接到另外一个mbuf前面
//输入:目标mbuf,源mbuf
//输出: 返回结果的地址(这里也是源mbuf的地址)
//**********************************************
mbufs *CMemCtrl::Linktof(mbufs *destbuf,mbufs *srcbuf)
{
srcbuf->m_nexts=destbuf;
return srcbuf;
}
//***********************************************
// 后向链接
//功能:将一个mbuf链接到另外一个mbuf后面
//输入:目标mbuf,源mbuf
//输出: 返回结果的地址(这里也是目的mbuf的地址)
//**********************************************
mbufs *CMemCtrl::Linktoe(mbufs *destbuf,mbufs *srcbuf)
{
destbuf->m_nexts=srcbuf;
return destbuf;
}
//**********************************************
// mbuf管理表的释放
//
//功能:把一个已经使用的mbuf释放为空闲,并放入空闲mbuf管理表的队列中
//输入:mbuf管理表指针
//输出:成功返回0 失败返回1
//**********************************************
bool CMemCtrl::PushMemtable(MemMTable *memtable)
{
if(!memtable)
{
return MRTNFALSE;
}
semTake(freemtQueSemmutex,-1); //获得信号量
//清空
memtable->next=0;
memtable->m_buf=0;
if(!freeEndptr)
{
freeEndptr=memtable;
freeHeadptr=freeEndptr;
}
else
{
freeEndptr->next=memtable;
freeEndptr=freeEndptr->next;
}
semGive(freemtQueSemmutex); //释放信号量
return MRTNTRUE;
}
//**********************************************
// mbuf管理表的申请
//
//功能:当释放一个mbuf的时候,需要调用这个函数申请一个空闲的管理表
// 然后将此表和释放的mbuf关联放入mbuf管理队列中。
//输入:无
//输出:成功返回一个空闲管理表的地址,失败返回0
//**********************************************
MemMTable *CMemCtrl::PopMemtable()
{
MemMTable *tempTable;
if(!freeHeadptr)
{
printf("没有可以申请的mbuf管理表 \n");
return MRTNNULL;
}
else
{
semTake(freemtQueSemmutex,-1); //获得信号量
if(freeHeadptr == freeEndptr)
{
tempTable=freeHeadptr;
freeHeadptr=0;
freeEndptr=freeHeadptr;
}
else
{
tempTable=freeHeadptr;
if(!freeHeadptr->next)
{
printf("CMBuf.cpp PopMemtable 错误 next为空 \n");
}
else
{
freeHeadptr=freeHeadptr->next;
}
}
semGive(freemtQueSemmutex); //释放信号量
}
return tempTable;
}
//************************************************
// 释放一个空闲簇管理表
//
//功能:释放一个空闲簇管理表到空闲簇表管理队列中
//输入:一个空闲簇表
//输出:成功返回0 失败返回1
//************************************************
bool CMemCtrl::PushExttable(ExtTable *exttable)
{
if(!exttable)
{
return MRTNFALSE;
}
semTake(freeextmtQueSemmutex,-1); //获得信号量
//清空
exttable->next=0;
exttable->extdatptr=0;
if(m_extfreeeptr==0)
{
m_extfreeeptr=exttable;
m_extfreehptr=exttable;
}
else
{
m_extfreeeptr->next=exttable;
m_extfreeeptr=m_extfreeeptr->next;
}
semGive(freeextmtQueSemmutex);
return MRTNTRUE;
}
//******************************************
// 申请一个空闲簇管理表
//
//功能:从空闲簇管理表队列中申请一个空闲簇
//输入:无
//输出:成功返回一个簇管理表的地址,失败返回0
//******************************************
ExtTable *CMemCtrl::PopExttable()
{
if(!m_extfreehptr)
{
return MRTNNULL;
}
else
{
ExtTable *tempexttable;
tempexttable=m_extfreehptr;
if(m_extfreehptr == m_extfreeeptr)
{
m_extfreehptr=0;
m_extfreeeptr=0;
}
else
{
m_extfreehptr=m_extfreehptr->next; //空闲簇表管理队列队首向后移动
}
return tempexttable;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -