基于linux的C语言的二维循环队列的设计(适用于高速帧数据缓存)

发布于:2022-11-02 ⋅ 阅读:(290) ⋅ 点赞:(0)

在linux应用程序开发过程中,通常会涉及到从高速数据接口(如网络socket、消息队列)接收数据并处理数据内容,但由于高速数据接口一般底层包含协议,如网络接口采用TCP/IP协议,采用帧作为数据传输的最小单位。为了linux应用程序正确读取高速数据接口数据、又不影响到系统其他接口功能、并保证待读取高速数据接口数据不丢失,一般会在应用程序添加二维循环队列作为缓存使用。从高速数据接口接收数据帧首先存入二维循环队列,待需要处理时再从循环队列中按数据帧读取数据。

本节介绍一种C语言设计的二维循环队列,该队列主要适用于网络通讯(含10/100/1000Mbps)TCP/UDP数据接收缓存、消息队列等以数据帧为最小单位的高速数据接口的数据缓存。

1、首先编写二维队列的头文件app_queue.h,头文件主要包括二维队列结构体的定义、参数宏定义等内容。

#ifndef SRC_APP_QUEUE_H_
#define SRC_APP_QUEUE_H_

#include <pthread.h>

#define	MAX_MESSAGE_FRAME_NUM	(2*1024)		//最大帧数量	2K	最大共16MB缓存
#define MAX_FRAME_SIZE			(8*1024)		//最大帧大小	8K


typedef struct Message_Queue
{
	unsigned char buffer[MAX_MESSAGE_FRAME_NUM][MAX_FRAME_SIZE];					//队列缓存指针
	unsigned int sizetab[MAX_MESSAGE_FRAME_NUM];	//每个队列中数据大小
//	unsigned int max_size;							//队列最大空间
	unsigned int read_index;						//读数据位置
	unsigned int write_index;						//写数据位置
	unsigned int count;								//队列数据量
	pthread_mutex_t mutex;
}message_queue;

extern message_queue	udpRevDataQueue;

int read_MessageQueue(message_queue *src_queue, unsigned char *data);
int write_MessageQueue(message_queue *dst_queue, unsigned char *data,unsigned int length);
void init_Queue_All(void);

#endif

2、然后编写二维队列的源文件app_queue.c,源文件主要包括二维队列结构体初始化、二维队列读写函数的实现。

#include 	<stdio.h>
#include 	<string.h>
#include 	"app_queue.h"


message_queue	udpRevDataQueue;	//接收udp命令队列

/******************************************************************************
*FUNCATION NAME  :	int write_MessageQueue(message_queue *dst_queue, unsigned char *data,unsigned int length)
*CREATE DATE     :	2022-11-02
*CREATE BY       :	LSL
*FUNCTION        :	二维队列写一帧数据,最大帧数据为2048字节
*MODIFY DATE     :
*INPUT           :	message_queue *dst_queue		待写入的消息队列指针
                    unsigned char *data				待写入的数据指针
					unsigned int length				待写入的帧数据字节数
*OUTPUT          :   
*RETURN          :  0 成功 -1失败
*OTHERS          :
******************************************************************************/
int write_MessageQueue(message_queue *dst_queue, unsigned char *data,unsigned int length)
{
	int rst = -1;

	if(NULL == dst_queue)
	{

		printf("write_message_queue err!\n");

		return rst;
	}

	if(dst_queue->count >= MAX_MESSAGE_FRAME_NUM)		//队列
	{

		printf("write_message_queue err 2,dst_queue->count=%d,max_size=%d\n",dst_queue->count,MAX_MESSAGE_FRAME_NUM);

		return rst;
	}
	pthread_mutex_lock(&dst_queue->mutex);
	memcpy((dst_queue->buffer[dst_queue->write_index]),data,length);//拷贝数据帧到队列中
	//*(dst_queue->buffer+dst_queue->write_index) = *data;
	dst_queue->sizetab[dst_queue->write_index]=length;
	dst_queue->write_index++;
	dst_queue->count++;
	if(dst_queue->write_index >= MAX_MESSAGE_FRAME_NUM)
	{
		dst_queue->write_index = 0;
	}
	pthread_mutex_unlock(&dst_queue->mutex);
	rst = length;
	return rst;
}
/******************************************************************************
*FUNCATION NAME  :	int read_MessageQueue(message_queue *src_queue, unsigned char *data)
*CREATE DATE     :	2022-11-02
*CREATE BY       :	LSL
*FUNCTION        :	二维队列读一帧数据,最大帧数据为2048字节
*MODIFY DATE     :
*INPUT           :	message_queue *dst_queue		待读取的消息队列指针
                    unsigned char *data				待读取的数据指针
*OUTPUT          :   
*RETURN          :  读取到帧数据字节数;小于0则读取失败
*OTHERS          :
******************************************************************************/
int read_MessageQueue(message_queue *src_queue, unsigned char *data)
{
	int rst = -1;
	int data_len;

	if(NULL==src_queue || NULL==data)
	{
		printf("read_MessageQueue Error!\n");
		return rst;
	}

	if(src_queue->count == 0)
	{
		return rst;
	}
	pthread_mutex_lock(&src_queue->mutex);
	data_len=src_queue->sizetab[src_queue->read_index];
	memcpy(data,src_queue->buffer[src_queue->read_index],data_len);//从队列中取出数据
	//*data = src_queue->buffer[src_queue->read_index];
	
	memset(src_queue->buffer[src_queue->read_index],0,data_len);
	src_queue->sizetab[src_queue->read_index]=0x00;//读取数据后,队列缓存清零
	src_queue->read_index++;
	src_queue->count--;
	if(src_queue->read_index >= MAX_MESSAGE_FRAME_NUM)
	{
		src_queue->read_index = 0;
	}
	//rst = 0;
	pthread_mutex_unlock(&src_queue->mutex);
	return data_len;
}
/******************************************************************************
*FUNCATION NAME  :      void init_MessageQueue(message_queue *src_queue)
*CREATE DATE     :      2022-11-02
*CREATE BY       :      LSL
*FUNCTION        :      初始化消息队列(二维队列)
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
void init_MessageQueue(message_queue *src_queue)
{
	src_queue->buffer[0][0] =0 ;
	src_queue->count = 0;
	src_queue->read_index = 0;
	//src_queue->recv_time = 0;
	src_queue->write_index = 0;

}
/******************************************************************************
*FUNCATION NAME  :	void init_queue_all(void)
*CREATE DATE     :	2021-11-02
*CREATE BY       :	LSL
*FUNCTION        :	初始化队列配置
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
void init_Queue_All(void)
{

	init_MessageQueue((message_queue *)&udpRevDataQueue);//初始化二维UDP接收队列

}

3、测试代码源文件文件如下所示:main.c,测试函数主要实现向二维队列写入多个递增数的数据帧,然后从二维队列读取数据帧,并对数据帧的内容进行判断,检验二维队列的工作有效性。

图1 main.c测试源码

 

4、Makefile文件为:

图2 Makefile文件

 

5、编译脚本build_myapp.sh为如下所示

图3 编译脚本

 

6、给编译脚本添加可执行权限,运行编译脚本生成可执行程序framemyapp:

图4 编译生成可执行程序

 

7、运行framemyapp的可执行程序,进行队列写入和队列读取数据的测试结果如下,下图为测试结果部分截图,未出现数据校验出错,说明二维循环队列工作正常:

图5 二维队列读写测试结果部分截图

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到