环形缓冲区

在生产者和消费者都只有一个的情况,环形缓冲区从实现机制上可以打到免锁的效果。环形缓冲区在相应中断处理速度方面效果非凡。

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值