实现原理
成块消息缓冲通过一个数组和读写指针实现,由一个成块消息缓冲结构体进行管理。
成块消息缓冲创建时通过系统堆申请内存,且是一次性把管理结构体和数据缓存空间整体分配,所以只能在内核中调用。
成块消息缓冲区与环形缓冲区的管理方式比较相似但也有些区别,其主要的区别在于成块消息管理在保证消息完整性上做了相应的处理,保证完整性的处理分为两个部分,分别是写消息时的处理与读消息时的处理。
实现源码
/*********************************************************************************************************
成块消息缓冲区结构
*********************************************************************************************************/
typedef struct {
PUCHAR BM_pucBuffer; /* 缓冲区首地址 */
size_t BM_stSize; /* 缓冲区大小 */
size_t BM_stLeft; /* 剩余空间大小 */
PUCHAR BM_pucPut; /* 写入指针 */
PUCHAR BM_pucGet; /* 读出指针 */
} LW_BMSG;
typedef LW_BMSG *PLW_BMSG;
#define LW_BMSG_MIN_SIZE 64 /* 最小缓冲区大小 */
#define LW_BMSG_PREFIX_LEN 2
/*********************************************************************************************************
** 函数名称: _bmsgCreate
** 功能描述: 创建一个 block msg 缓冲区
** 输 入 : stSize 缓冲区大小
** 输 出 : 新建的缓冲区
*********************************************************************************************************/
PLW_BMSG _bmsgCreate (size_t stSize)
{
PLW_BMSG pbmsg;
if (stSize < LW_BMSG_MIN_SIZE) {
_ErrorHandle(EINVAL);
return (LW_NULL);
}
pbmsg = (PLW_BMSG)__SHEAP_ALLOC(sizeof(LW_BMSG) + stSize);
if (!pbmsg) {
_ErrorHandle(ENOMEM);
return (LW_NULL);
}
pbmsg->BM_pucBuffer = (PUCHAR)pbmsg + sizeof(LW_BMSG);
pbmsg->BM_stSize = stSize;
pbmsg->BM_stLeft = stSize;
pbmsg->BM_pucPut = pbmsg->BM_pucBuffer;
pbmsg->BM_pucGet = pbmsg->BM_pucBuffer;
return (pbmsg);
}
/*********************************************************************************************************
** 函数名称: _bmsgDelete
** 功能描述: 删除一个 block msg 缓冲区
** 输 入 : pbmsg 缓冲区
** 输 出 : NONE
*********************************************************************************************************/
VOID _bmsgDelete (PLW_BMSG pbmsg)
{
__SHEAP_FREE(pbmsg);
}
/*********************************************************************************************************
** 函数名称: _bmsgPut
** 功能描述: 将一条数据存入 block msg 缓冲区
** 输 入 : pbmsg 缓冲区
** pvMsg 消息
** stSize 消息长度 (不能大于 65535)
** 输 出 : 保存的字节数
*********************************************************************************************************/
INT _bmsgPut (PLW_BMSG pbmsg, CPVOID pvMsg, size_t stSize)
{
#define LW_BMSG_ADJUST_PUT() \
if (pbmsg->BM_pucPut >= (pbmsg->BM_pucBuffer + pbmsg->BM_stSize)) { \
pbmsg->BM_pucPut = pbmsg->BM_pucBuffer; \
}
size_t stLen;
size_t stSave = stSize + LW_BMSG_PREFIX_LEN;
if (stSave >= (UINT16)(~0)) {
return (0);
}
if (pbmsg->BM_stLeft < stSave) {
return (0);
}
*pbmsg->BM_pucPut = (UCHAR)(stSize >> 8); /* 保存两个字节长度信息 */
pbmsg->BM_pucPut++;
LW_BMSG_ADJUST_PUT();
*pbmsg->BM_pucPut = (UCHAR)(stSize & 0xff);
pbmsg->BM_pucPut++;
LW_BMSG_ADJUST_PUT();
stLen = (pbmsg->BM_pucBuffer + pbmsg->BM_stSize) - pbmsg->BM_pucPut;
if (stLen >= stSize) {
lib_memcpy(pbmsg->BM_pucPut, pvMsg, stSize);
if (stLen > stSize) {
pbmsg->BM_pucPut += stSize;
} else {
pbmsg->BM_pucPut = pbmsg->BM_pucBuffer;
}
} else {
lib_memcpy(pbmsg->BM_pucPut, pvMsg, stLen);
pbmsg->BM_pucPut = pbmsg->BM_pucBuffer;
lib_memcpy(pbmsg->BM_pucPut, (PUCHAR)pvMsg + stLen, stSize - stLen);
pbmsg->BM_pucPut += (stSize - stLen);
}
pbmsg->BM_stLeft -= stSave;
return ((INT)stSize);
}
/*********************************************************************************************************
** 函数名称: _bmsgGet
** 功能描述: 从 block msg 缓冲区取出一条消息
** 输 入 : pbmsg 缓冲区
** pvMsg 接收缓冲
** stBufferSize 接收缓冲长度
** 输 出 : 获取的字节数
*********************************************************************************************************/
INT _bmsgGet (PLW_BMSG pbmsg, PVOID pvMsg, size_t stBufferSize)
{
#define LW_BMSG_ADJUST_GET() \
if (pbmsg->BM_pucGet >= (pbmsg->BM_pucBuffer + pbmsg->BM_stSize)) { \
pbmsg->BM_pucGet = pbmsg->BM_pucBuffer; \
}
size_t stLen;
size_t stSize;
UCHAR ucHigh;
UCHAR ucLow;
stLen = pbmsg->BM_stSize - pbmsg->BM_stLeft;
if (stLen == 0) {
return (0);
}
ucHigh = pbmsg->BM_pucGet[0];
if ((pbmsg->BM_pucGet - pbmsg->BM_pucBuffer) >= pbmsg->BM_stSize) {
ucLow = pbmsg->BM_pucBuffer[0];
} else {
ucLow = pbmsg->BM_pucGet[1];
}
stSize = (size_t)((ucHigh << 8) + ucLow);
if (stSize > stBufferSize) {
return (PX_ERROR); /* 缓冲区太小 */
}
pbmsg->BM_pucGet++;
LW_BMSG_ADJUST_GET();
pbmsg->BM_pucGet++;
LW_BMSG_ADJUST_GET();
stLen = (pbmsg->BM_pucBuffer + pbmsg->BM_stSize) - pbmsg->BM_pucGet;
if (stLen >= stSize) {
lib_memcpy(pvMsg, pbmsg->BM_pucGet, stSize);
if (stLen > stSize) {
pbmsg->BM_pucGet += stSize;
} else {
pbmsg->BM_pucGet = pbmsg->BM_pucBuffer;
}
} else {
lib_memcpy(pvMsg, pbmsg->BM_pucGet, stLen);
pbmsg->BM_pucGet = pbmsg->BM_pucBuffer;
lib_memcpy((PUCHAR)pvMsg + stLen, pbmsg->BM_pucGet, stSize - stLen);
pbmsg->BM_pucGet += (stSize - stLen);
}
pbmsg->BM_stLeft += (stSize + LW_BMSG_PREFIX_LEN);
return ((INT)stSize);
}
/*********************************************************************************************************
** 函数名称: _bmsgFlush
** 功能描述: 清空 block msg 缓冲区
** 输 入 : pbmsg 缓冲区
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID _bmsgFlush (PLW_BMSG pbmsg)
{
pbmsg->BM_stLeft = pbmsg->BM_stSize;
pbmsg->BM_pucPut = pbmsg->BM_pucBuffer;
pbmsg->BM_pucGet = pbmsg->BM_pucBuffer;
}
/*********************************************************************************************************
** 函数名称: _bmsgIsEmpty
** 功能描述: block msg 缓冲区是否为空
** 输 入 : pbmsg 缓冲区
** 输 出 : 是否为空
*********************************************************************************************************/
INT _bmsgIsEmpty (PLW_BMSG pbmsg)
{
return (pbmsg->BM_stLeft == pbmsg->BM_stSize);
}
/*********************************************************************************************************
** 函数名称: _bmsgIsFull
** 功能描述: block msg 缓冲区是否为满
** 输 入 : pbmsg 缓冲区
** 输 出 : 是否已满
*********************************************************************************************************/
INT _bmsgIsFull (PLW_BMSG pbmsg)
{
return (pbmsg->BM_stLeft < (LW_BMSG_PREFIX_LEN + 1));
}
/*********************************************************************************************************
** 函数名称: _bmsgSizeGet
** 功能描述: block msg 缓冲区大小
** 输 入 : pbmsg 缓冲区
** 输 出 : 总大小
*********************************************************************************************************/
size_t _bmsgSizeGet (PLW_BMSG pbmsg)
{
return (pbmsg->BM_stSize);
}
/*********************************************************************************************************
** 函数名称: _bmsgFreeByte
** 功能描述: block msg 缓冲区剩余空间大小
** 输 入 : pbmsg 缓冲区
** 输 出 : 剩余空间大小
*********************************************************************************************************/
INT _bmsgFreeByte (PLW_BMSG pbmsg)
{
if (pbmsg->BM_stLeft < (LW_BMSG_PREFIX_LEN + 1)) {
return (0);
} else {
return ((INT)(pbmsg->BM_stLeft - (LW_BMSG_PREFIX_LEN + 1)));
}
}
/*********************************************************************************************************
** 函数名称: _bmsgNBytes
** 功能描述: block msg 缓冲区总信息量
** 输 入 : pbmsg 缓冲区
** 输 出 : 总信息大小
*********************************************************************************************************/
INT _bmsgNBytes (PLW_BMSG pbmsg)
{
return ((INT)(pbmsg->BM_stSize - pbmsg->BM_stLeft));
}
/*********************************************************************************************************
** 函数名称: _bmsgNBytesNext
** 功能描述: block msg 缓冲区下一条信息长度
** 输 入 : pbmsg 缓冲区
** 输 出 : 下一条信息长度
*********************************************************************************************************/
INT _bmsgNBytesNext (PLW_BMSG pbmsg)
{
size_t stSize;
UCHAR ucHigh;
UCHAR ucLow;
if (pbmsg->BM_stSize == pbmsg->BM_stLeft) {
return (0);
}
ucHigh = pbmsg->BM_pucGet[0];
if ((pbmsg->BM_pucGet - pbmsg->BM_pucBuffer) >= pbmsg->BM_stSize) {
ucLow = pbmsg->BM_pucBuffer[0];
} else {
ucLow = pbmsg->BM_pucGet[1];
}
stSize = (size_t)((ucHigh << 8) + ucLow);
return ((INT)stSize);
}