⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmbuf.cpp

📁 可以用于vxworks的mbuf的自己设计的实现方式
💻 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 + -