栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言简单实现环形缓冲及验证

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言简单实现环形缓冲及验证

文章目录
  • 前言
  • 一、环形缓冲是什么?
    • 1. 定义
    • 2.参数描述
  • 二、环形缓冲的C实现
    • 1.环形缓冲模块代码
    • 2.测试验证代码
  • 三、测试结果


前言

最近发现,无论是底层还是上层,亦或是CPU运行,都离不开缓存(广义的),缓存的最大用处当然是缓存数据,同时还有一大用处就是隔离功能模块,这对于软件的模块化来说实在太有意义了。
环形缓冲作为一个工具类模块,在项目中其实一直在使用,不过其实现是其他大佬实现的,功能完善且强大,今天突然心血来潮,想按自己的理解实现一下,加深一下对其的理解。


一、环形缓冲是什么?

先啰嗦两句定义再上代码,哈哈……

1. 定义

这里引用百度百科:环形缓冲,也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),圆形缓冲区(circula buffer),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。

具体请参考:环形缓冲百度百科

2.参数描述

要实现环形缓冲功能,根据我的理解梳理,如下参数可完整描述一个环形缓冲:

二、环形缓冲的C实现

代码实现包括两部分,一个是环形缓冲的模块代码(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 代码如下:

#include 
#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;
}
2.测试验证代码

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

三、测试结果

运行结果截图:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1030336.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号