- 前言
- 一、环形缓冲是什么?
- 1. 定义
- 2.参数描述
- 二、环形缓冲的C实现
- 1.环形缓冲模块代码
- 2.测试验证代码
- 三、测试结果
前言
最近发现,无论是底层还是上层,亦或是CPU运行,都离不开缓存(广义的),缓存的最大用处当然是缓存数据,同时还有一大用处就是隔离功能模块,这对于软件的模块化来说实在太有意义了。
环形缓冲作为一个工具类模块,在项目中其实一直在使用,不过其实现是其他大佬实现的,功能完善且强大,今天突然心血来潮,想按自己的理解实现一下,加深一下对其的理解。
一、环形缓冲是什么?
先啰嗦两句定义再上代码,哈哈……
1. 定义这里引用百度百科:环形缓冲,也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),圆形缓冲区(circula buffer),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。
具体请参考:环形缓冲百度百科
要实现环形缓冲功能,根据我的理解梳理,如下参数可完整描述一个环形缓冲:
代码实现包括两部分,一个是环形缓冲的模块代码(ring_fifo.c和ring_fifo.h),一个是测试验证代码(test_ring_fifo.c),话不多说,下面直接上代码。
1.环形缓冲模块代码ring_fifo.h 代码如下:
#ifndef __RING_FIFO #define __RING_FIFO int open_ring_fifo(int iSize); int close_ring_fifo(int iHandle); int read_ring_fifo(int iHandle, char *pData, int iLen); int write_ring_fifo(int iHandle, char *pData, int iLen); #endif
ring_fifo.c 代码如下:
#include2.测试验证代码#include #include #include #include #include "ring_fifo.h" typedef struct _ring_fifo { int iSize; char *pStart; char *pEnd; char *pRead; char *pWrite; int iAreadyReadLen; int iAreadyWriteLen; int iLeftReadLen; int iLeftWriteLen; pthread_mutex_t mLock; }ring_fifo_t; int open_ring_fifo(int iSize) { if (iSize == 0) { printf("can not create 0 byte fifo"); return -1; } ring_fifo_t *pstRingFifo = (ring_fifo_t *)malloc(sizeof(ring_fifo_t)); if (pstRingFifo == NULL) { printf("ring_fifo_t malloc failn"); return -1; } memset(pstRingFifo, 0, sizeof(ring_fifo_t)); pstRingFifo->iSize = iSize; pstRingFifo->pStart = (char *)malloc(iSize); if (pstRingFifo->pStart == NULL) { printf("ring fifo malloc failn"); free(pstRingFifo); return -1; } memset(pstRingFifo->pStart, 0, iSize); pstRingFifo->pEnd = pstRingFifo->pStart + iSize; pstRingFifo->pRead = pstRingFifo->pWrite = pstRingFifo->pStart; pstRingFifo->iLeftReadLen = 0; pstRingFifo->iLeftWriteLen = iSize; pthread_mutex_init(&pstRingFifo->mLock, NULL); printf("open ring fifo(%p) successn", pstRingFifo); return (int)pstRingFifo; } int close_ring_fifo(int iHandle) { if (iHandle == 0) { printf("bad param!n"); return -1; } ring_fifo_t *pstRingFifo = (ring_fifo_t *)iHandle; pthread_mutex_destroy(&pstRingFifo->mLock); free(pstRingFifo->pStart); free(pstRingFifo); printf("close ring fifo(%p) successn", pstRingFifo); return 0; } int read_ring_fifo(int iHandle, char *pData, int iLen) { if (iHandle == 0) { printf("bad param!n"); return -1; } ring_fifo_t *pstRingFifo = (ring_fifo_t *)iHandle; pthread_mutex_lock(&pstRingFifo->mLock); if (pstRingFifo->iLeftReadLen < iLen) { printf("left read len too short(%d<%d)n", pstRingFifo->iLeftReadLen, iLen); pthread_mutex_unlock(&pstRingFifo->mLock); return 0; } if (pstRingFifo->pEnd - pstRingFifo->pRead >= iLen ) { memcpy(pData, pstRingFifo->pRead, iLen); pstRingFifo->pRead += iLen; } else { memcpy(pData, pstRingFifo->pRead, pstRingFifo->pEnd - pstRingFifo->pRead); memcpy(pData + (pstRingFifo->pEnd - pstRingFifo->pRead), pstRingFifo->pStart, iLen - (pstRingFifo->pEnd - pstRingFifo->pRead)); pstRingFifo->pRead = pstRingFifo->pRead + iLen - pstRingFifo->iSize; } pstRingFifo->iLeftReadLen -= iLen; pstRingFifo->iLeftWriteLen += iLen; pstRingFifo->iAreadyReadLen += iLen; printf("pRead:%p,iAreadyReadLen:%d,iFifoSize:%dn", pstRingFifo->pRead, pstRingFifo->iAreadyReadLen, pstRingFifo->iSize); pthread_mutex_unlock(&pstRingFifo->mLock); return iLen; } int write_ring_fifo(int iHandle, char *pData, int iLen) { if (iHandle == 0) { printf("bad param!n"); return -1; } ring_fifo_t *pstRingFifo = (ring_fifo_t *)iHandle; pthread_mutex_lock(&pstRingFifo->mLock); if (pstRingFifo->iLeftWriteLen < iLen) { printf("left write len too short(%d<%d)n", pstRingFifo->iLeftReadLen, iLen); pthread_mutex_unlock(&pstRingFifo->mLock); return 0; } if ((pstRingFifo->pEnd - pstRingFifo->pWrite) >= iLen) { memcpy(pstRingFifo->pWrite, pData, iLen); pstRingFifo->pWrite += iLen; } else { memcpy(pstRingFifo->pWrite, pData, pstRingFifo->pEnd - pstRingFifo->pWrite); memcpy(pstRingFifo->pStart, pData + (pstRingFifo->pEnd - pstRingFifo->pWrite), iLen - (pstRingFifo->pEnd - pstRingFifo->pWrite)); pstRingFifo->pWrite = pstRingFifo->pWrite + iLen - pstRingFifo->iSize; } pstRingFifo->iLeftWriteLen -= iLen; pstRingFifo->iLeftReadLen += iLen; pstRingFifo->iAreadyWriteLen += iLen; printf("pWrite:%p,iAreadyWriteLen:%d,iFifoSize:%dn", pstRingFifo->pWrite, pstRingFifo->iAreadyWriteLen, pstRingFifo->iSize); pthread_mutex_unlock(&pstRingFifo->mLock); return iLen; }
test_ring_fifo.c 代码如下:
#include#include #include #include #include #include "ring_fifo.h" char g_TestData[] = "hello world"; #define TEST_LEN (sizeof(g_TestData)) void* pthread_read(void *arg) { pthread_detach(pthread_self()); int iHandle = *(int *)arg; char buf[1024] = {' '}; int iReadLen = 0; while(1) { iReadLen = read_ring_fifo(iHandle, buf, TEST_LEN); if (iReadLen == 0) { usleep(10 * 1000); continue; } else if(iReadLen < 0) { printf("read ring fifo error!n"); break; } printf("read ring fifo: %snn", buf); sleep(1); } return NULL; } void* pthread_write(void *arg) { pthread_detach(pthread_self()); int iHandle = *(int *)arg; int iWriteLen = 0; while(1) { iWriteLen = write_ring_fifo(iHandle, g_TestData, TEST_LEN); if (iWriteLen == 0) { usleep(10 * 1000); continue; } else if(iWriteLen < 0) { printf("write ring fifo error!n"); break; } printf("write ring fifo: %sn", g_TestData); sleep(1); } return NULL; } int main(void) { printf("sizeof(int) = %d, sizeof(void *) = %dn", sizeof(int), sizeof(void *)); int iHandle = 0; pthread_t ptidR; pthread_t ptidW; iHandle = open_ring_fifo(1024); if (iHandle <= 0) { printf("open ring fifo failn"); return -1; } pthread_create(&ptidR, NULL, pthread_read, &iHandle); pthread_create(&ptidW, NULL, pthread_write, &iHandle); while(getchar()!='q') { usleep(10 * 1000); } close_ring_fifo(iHandle); return 0; }
三、测试结果
运行结果截图:



