在生产者和消费者都只有一个的情况,环形缓冲区从实现机制上可以打到免锁的效果。环形缓冲区在相应中断处理速度方面效果非凡。
#include "stdafx.h" #include "stdio.h" #include "memory.h" typedef unsigned long ULONG; typedef unsigned short USHORT; typedef unsigned char UCHAR; #define NULL_PTR NULL #define VOID void #define VOS_OK 0 #define VOS_ERR 1 #define SIZE_OF_TL (5) typedef struct tagTlv { UCHAR ucType; /* TLV类型 */ UCHAR ucLen1; /* TLV长度24-31比特 */ UCHAR ucLen2; /* TLV长度16-23比特 */ UCHAR ucLen3; /* TLV长度08-15比特 */ UCHAR ucLen4; /* TLV长度00-07比特 */ UCHAR aucValue[3]; /* 保留位,四字节对齐 */ } TLV_S; #define RING_BUFFER_SIZE (30) typedef struct tagRingBuffer { ULONG ulUsedBufferSize; /* 环形缓冲区已使用空间大小 */ UCHAR ucType; /* 通过TLV结构保存数据,代表Type */ UCHAR ucSrv[3]; /* 保留位,四字节对齐 */ UCHAR *pucReadCursor; /* 数据读取游标 */ UCHAR *pucWriteCursor; /* 数据写入游标 */ UCHAR aucBuffer[RING_BUFFER_SIZE]; /* 缓冲区 */ } RING_BUFFER_S; RING_BUFFER_S g_stRingBuffer; /************************************************************************ * 功能描述:初始化环形缓冲区 * 参数说明:UCHAR ucType 环形缓冲区TLV类型 * 原理说明: * 返 回 值:环形缓冲区指针 *************************************************************************/ VOID *VOS_InitRingBuffer(UCHAR ucType) { g_stRingBuffer.ulUsedBufferSize = 0; g_stRingBuffer.ucType = ucType; g_stRingBuffer.pucReadCursor = g_stRingBuffer.aucBuffer; g_stRingBuffer.pucWriteCursor = g_stRingBuffer.aucBuffer; return &g_stRingBuffer; } /************************************************************************ * 功能描述:获取环形缓冲区已使用空间大小 * 参数说明:VOID *pRingBuffer 环形缓冲区指针 * 原理说明: * 返 回 值:已使用空间大小 *************************************************************************/ ULONG VOS_GetUsedRingBufferSize(VOID *pRingBuffer) { RING_BUFFER_S *pstRingBuffer; /* 内部函数不检查参数合法性 */ pstRingBuffer = (RING_BUFFER_S *)(pRingBuffer); return pstRingBuffer->ulUsedBufferSize; } /************************************************************************ * 功能描述:获取环形缓冲区空闲空间大小 * 参数说明:VOID *pRingBuffer 环形缓冲区指针 * 原理说明: * 返 回 值:ULONG 空闲空间大小 *************************************************************************/ ULONG VOS_GetFreeRingBufferSize(VOID *pRingBuffer) { RING_BUFFER_S *pstRingBuffer; /* 内部函数不检查参数合法性 */ pstRingBuffer = (RING_BUFFER_S *)(pRingBuffer); return (sizeof(pstRingBuffer->aucBuffer) - pstRingBuffer->ulUsedBufferSize); } /************************************************************************ * 功能描述:智能拷贝数据到环形缓冲区 * 参数说明:UCHAR *pucRingBuffer 环形缓冲区指针 ULONG ulRingBufferSize 环形缓冲区大小 UCHAR *pucDst 数据拷贝目的指针(位于环形缓冲区内) UCHAR *pucSrc 数据拷贝源指针 ULONG ulSrcSize 数据拷贝大小 * 原理说明: * 返 回 值:CUAHR * 拷贝完数据后指针 *************************************************************************/ UCHAR *VOS_SmartCopyInfoBuffer(UCHAR *pucRingBuffer, ULONG ulRingBufferSize, UCHAR *pucDst, UCHAR *pucSrc, ULONG ulSrcSize) { ULONG ulTailLen; UCHAR *pucCopyEnd; /* 函数参数合法性检查 */ if ((NULL == pucRingBuffer) || (NULL_PTR == pucDst) || (NULL_PTR == pucSrc)) { return NULL_PTR; } /* 获取环形缓冲区尾部可用空间大小 */ ulTailLen = (ULONG)((pucRingBuffer + ulRingBufferSize) - pucDst); if (ulTailLen >= ulSrcSize) { /* 环形缓冲区尾部空间足够时,直接拷贝数据到尾部 */ memcpy(pucDst, pucSrc, ulSrcSize); pucCopyEnd = pucDst + ulSrcSize; } else { /* 环形缓冲区尾部空间不足时,拷贝部分数据到尾部,然后再拷贝数据到头部 */ memcpy(pucDst, pucSrc, ulTailLen); memcpy(pucRingBuffer, pucSrc + ulTailLen, ulSrcSize - ulTailLen); pucCopyEnd = pucRingBuffer + (ulSrcSize - ulTailLen); } return pucCopyEnd; } /************************************************************************ * 功能描述:智能从环形缓冲区拷贝数据 * 参数说明:UCHAR *pucRingBuffer 环形缓冲区指针 ULONG ulRingBufferSize 环形缓冲区大小 UCHAR *pucSrc 数据拷贝源指针(位于环形缓冲区内) UCHAR *pucDst 数据拷贝目的指针 ULONG ulDstSize 数据拷贝大小 * 原理说明: * 返 回 值:UCHAR * 拷贝完数据后指针 *************************************************************************/ UCHAR *VOS_SmartCopyFromBuffer(UCHAR *pucRingBuffer, ULONG ulRingBufferSize, UCHAR *pucSrc, UCHAR *pucDst, ULONG ulDstSize) { ULONG ulTailLen; UCHAR *pucCopyEnd; /* 函数参数合法性检查 */ if ((NULL == pucRingBuffer) || (NULL_PTR == pucSrc) || (NULL_PTR == pucDst)) { return NULL_PTR; } /* 获取环形缓冲区尾部空间大小 */ ulTailLen = (ULONG)((pucRingBuffer + ulRingBufferSize) - pucSrc); if (ulTailLen >= ulDstSize) { /* 环形缓冲区尾部空间足够时,直接从尾部拷贝数据 */ memcpy(pucDst, pucSrc, ulDstSize); pucCopyEnd = pucSrc + ulDstSize; } else { /* 环形缓冲区尾部空间不足时,从尾部拷贝部分数据,然后再从头部拷贝数据 */ memcpy(pucDst, pucSrc, ulTailLen); memcpy(pucDst + ulTailLen, pucRingBuffer, ulDstSize - ulTailLen); pucCopyEnd = pucRingBuffer + (ulDstSize - ulTailLen); } return pucCopyEnd; } /************************************************************************ * 功能描述:将用户数据压入环形缓冲区 * 参数说明:VOID *pRingBuffer 环形缓冲区指针 VOID *pFrameBuffer 用户数据指针 ULONG ulFrameBufferLen 用户数据大小 * 原理说明: * 返 回 值:VOS_OK 数据压入环形缓冲区成功 VOS_ERR 数据压入环形缓冲区失败 *************************************************************************/ ULONG VOS_PushBuffer(VOID *pRingBuffer, VOID *pFrameBuffer, ULONG ulFrameBufferLen) { ULONG ulFreeRingBufferSize; TLV_S stTlv; UCHAR *pucCopyEnd; RING_BUFFER_S *pstRingBuffer; /* 函数参数合法性检查 */ if ((NULL_PTR == pRingBuffer) || (NULL_PTR == pFrameBuffer)) { return VOS_ERR; } pstRingBuffer = (RING_BUFFER_S *)pRingBuffer; /* 获取环形缓冲区可用空间 */ ulFreeRingBufferSize = VOS_GetFreeRingBufferSize(pstRingBuffer); /* 环形缓冲区可用空间不足 */ if (ulFreeRingBufferSize < (ulFrameBufferLen + SIZE_OF_TL)) { return VOS_ERR; } /* 写入TL字段 */ stTlv.ucType = pstRingBuffer->ucType; stTlv.ucLen1 = (UCHAR)((ulFrameBufferLen >> 24) & 0xFF); stTlv.ucLen2 = (UCHAR)((ulFrameBufferLen >> 16) & 0xFF); stTlv.ucLen3 = (UCHAR)((ulFrameBufferLen >> 8) & 0xFF); stTlv.ucLen4 = (UCHAR)((ulFrameBufferLen >> 0) & 0xFF); pucCopyEnd = VOS_SmartCopyInfoBuffer(pstRingBuffer->aucBuffer, sizeof(pstRingBuffer->aucBuffer), pstRingBuffer->pucWriteCursor, (UCHAR *)(&stTlv), SIZE_OF_TL); pstRingBuffer->pucWriteCursor = pucCopyEnd; pstRingBuffer->ulUsedBufferSize += SIZE_OF_TL; /* 写入用户数据 */ pucCopyEnd = VOS_SmartCopyInfoBuffer(pstRingBuffer->aucBuffer, sizeof(pstRingBuffer->aucBuffer), pstRingBuffer->pucWriteCursor, (UCHAR *)(pFrameBuffer), ulFrameBufferLen); pstRingBuffer->pucWriteCursor = pucCopyEnd; pstRingBuffer->ulUsedBufferSize += ulFrameBufferLen; return VOS_OK; } /************************************************************************ * 功能描述:从环形缓冲区读取数据 * 参数说明:VOID *pRingBuffer 环形缓冲区指针 VOID *pFrameBuffer 用户数据指针(用户保证内存不存在越界) ULONG *pulFrameBufferLen用户数据大小 * 原理说明: * 返 回 值:VOS_OK 数据压入环形缓冲区成功 VOS_ERR 数据压入环形缓冲区失败 *************************************************************************/ ULONG VOS_PopBuffer(VOID *pRingBuffer, VOID *pFrameBuffer, ULONG *pulFrameBufferLen) { ULONG ulUsedRingBufferSize; ULONG ulFrameBufferLen; TLV_S stTlv; UCHAR *pucCopyEnd; RING_BUFFER_S *pstRingBuffer; /* 函数参数合法性检查 */ if ((NULL_PTR == pRingBuffer) || (NULL_PTR == pFrameBuffer) || (NULL_PTR == pulFrameBufferLen)) { return VOS_ERR; } pstRingBuffer = (RING_BUFFER_S *)pRingBuffer; /* 获取环形缓冲区已用空间 */ ulUsedRingBufferSize = VOS_GetUsedRingBufferSize(pstRingBuffer); /* 环形缓冲区无使用空间,不存在用户数据 */ if (0 == ulUsedRingBufferSize) { return VOS_ERR; } /* 读取TL字段 */ pucCopyEnd = VOS_SmartCopyFromBuffer(pstRingBuffer->aucBuffer, sizeof(pstRingBuffer->aucBuffer), pstRingBuffer->pucReadCursor, (UCHAR *)(&stTlv), SIZE_OF_TL); if (stTlv.ucType != pstRingBuffer->ucType) { return VOS_ERR; } pstRingBuffer->pucReadCursor = pucCopyEnd; pstRingBuffer->ulUsedBufferSize -= SIZE_OF_TL; /* 读取用户数据 */ ulFrameBufferLen = (stTlv.ucLen1 << 24) + (stTlv.ucLen2 << 16) + (stTlv.ucLen3 << 8) + (stTlv.ucLen4 << 0); pucCopyEnd = VOS_SmartCopyFromBuffer(pstRingBuffer->aucBuffer, sizeof(pstRingBuffer->aucBuffer), pstRingBuffer->pucReadCursor, (UCHAR *)(pFrameBuffer), ulFrameBufferLen); pstRingBuffer->pucReadCursor = pucCopyEnd; pstRingBuffer->ulUsedBufferSize -= ulFrameBufferLen; /* 回填返回数据大小 */ *pulFrameBufferLen = ulFrameBufferLen; return VOS_OK; }
原文:http://blog.csdn.net/bessics/article/details/23390955