?? 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
{
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 + -