一、实现原理如下图所示
环形队列实现需注意以下四点(本质上是和“3、一个简单队列的实现”一样的):
(1)往队列中写数据
memcpy(&g_tQue[g_iWritePos],pNode,sizeof(T_QUEUE));
g_iWritePos = (g_iWritePos + 1) % QUEUE_SIZE_MAX;
(2)从队列中读出数据
memcpy(pNode,&g_tQue[g_iReadPos],sizeof(T_QUEUE));
g_iReadPos = (g_iReadPos + 1) % QUEUE_SIZE_MAX;
(3)队列放满数据
((g_iWritePos + 1) % QUEUE_SIZE_MAX) == g_iReadPos),下一个要写的位置等于要读的位置,
则队列放满,实际上队列满的时候,里边存放的QUEUE_SIZE_MAX - 1个数据,这样做是为了和空
队列加以区分管
(4)队列为空(没有数据)
g_iWritePos == g_iReadPos,当前要写的位置等于当前要写的位置,则队列为空
二、代码实现如下
(1)简单实现
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 #define QUEUE_SIZE_MAX 10 6 #define MY_BUF_SIZE 128 7 8 typedef struct{ 9 int type; 10 int reserve; 11 int buf[MY_BUF_SIZE]; 12 }T_QUEUE; 13 14 static T_QUEUE g_tQue[QUEUE_SIZE_MAX]; 15 16 static int g_iReadPos = 0; 17 static int g_iWritePos = 0;; 18 19 static int isFull(void) 20 { 21 return (((g_iWritePos + 1) % QUEUE_SIZE_MAX) == g_iReadPos); 22 } 23 24 static int isEmpty(void) 25 { 26 return (g_iWritePos == g_iReadPos); 27 } 28 29 static int PutData(T_QUEUE *pNode) 30 { 31 if (isFull()) 32 { 33 printf("queque is overflow!\r\n"); 34 return -1; 35 } 36 else 37 { 38 memcpy(&g_tQue[g_iWritePos],pNode,sizeof(T_QUEUE)); 39 g_iWritePos = (g_iWritePos + 1) % QUEUE_SIZE_MAX; 40 return 0; 41 } 42 } 43 44 static int GetData(T_QUEUE *pNode) 45 { 46 if (isEmpty()) 47 { 48 printf("queque is empty!\r\n"); 49 return -1; 50 } 51 else 52 { 53 memcpy(pNode,&g_tQue[g_iReadPos],sizeof(T_QUEUE)); 54 g_iReadPos = (g_iReadPos + 1) % QUEUE_SIZE_MAX; 55 } 56 57 }
(2)通用型
<1>创建ring_queue.c文件
1 // 初始化队列 2 int ring_queue_init(int* piWritePos, int* piReadPos) 3 { 4 *piWritePos = 0; 5 *piReadPos = 0; 6 return 0; 7 } 8 9 // 队列是否已满 10 int isFull(int* piWritePos, int* piReadPos, int iQueSizeMax) 11 { 12 return (((*piWritePos + 1) % iQueSizeMax) == *piReadPos); 13 } 14 15 // 队列是否为空 16 int isEmpty(int* piWritePos, int* piReadPos) 17 { 18 return (*piWritePos == *piWritePos); 19 } 20 21 // 队列中放入数据 22 int PutData(int* piWritePos, int* piReadPos, void *tQue, void *pNode, int iQueSizeMax, int NodeSize) 23 { 24 25 if (isFull(piWritePos,piReadPos,iQueSizeMax)) 26 { 27 printf("queque is overflow!\r\n"); 28 return -1; 29 } 30 else 31 { 32 memcpy(tQue + (*piWritePos) * NodeSize,pNode,NodeSize); 33 *piWritePos = (*piWritePos + 1) % iQueSizeMax; 34 return 0; 35 } 36 } 37 38 // 从队列中取数据 39 int GetData(int* piWritePos, int* piReadPos, void *tQue, void *pNode, int iQueSizeMax, int NodeSize) 40 { 41 if (isEmpty(piWritePos,piReadPos)) 42 { 43 printf("queque is empty!\r\n"); 44 return -1; 45 } 46 else 47 { 48 memcpy(pNode,tQue + (*piReadPos) * NodeSize,NodeSize); 49 *piReadPos = (*piReadPos + 1) % iQueSizeMax; 50 return 0; 51 } 52 53 }
<2>创建example1.c文件
1 #define DATA_ARRAY_MAX (5) 2 #define MAX_DATA_SIZE (64) 3 #define MSG_BUF_SIZE (64) 4 typedef struct 5 { 6 unsigned long hid; 7 unsigned long cid; 8 unsigned char type; 9 unsigned char len; 10 unsigned char chksum; 11 unsigned char seq; 12 unsigned char userData[MAX_DATA_SIZE]; 13 }DATA_T; 14 15 typedef struct 16 { 17 unsigned int version; 18 unsigned int channel; 19 unsigned int reserve; 20 }DATA_INFO_T; 21 22 23 typedef struct{ 24 int type; 25 int data; 26 int arBuf[MSG_BUF_SIZE]; 27 }ITEM_MSG_T; 28 29 typedef enum 30 { 31 RECV_PORT1_DATA, 32 RECV_PORT2_DATA, 33 RECV_PORT3_DATA, 34 }MSG_TYPE_E; 35 typedef enum 36 { 37 GET_BD_INFO_REQ, 38 GET_BD_INFO_RES, 39 }DATA_TYPE_E; 40 41 int g_iQin = 0; 42 int g_iQout = 0; 43 44 static unsigned char tx_buf[sizeof(DATA_T)]; 45 46 static DATA_T g_tArray[DATA_ARRAY_MAX]; 47 /***************************************************************** 48 * @brief 初始化队列 49 * 50 * @param no 51 * 52 *@retval no 53 * 54 *****************************************************************/ 55 void Example1_init(void) 56 { 57 ring_queue_init(&g_iQin, &g_iQout); 58 } 59 60 /***************************************************************** 61 * @brief 把数据放入队列 62 * 63 * @param pData 指向要放入队列的数据 64 * 65 * @param len 数据长度 66 * 67 *@retval len 放入队列的数据长度 68 * 69 *****************************************************************/ 70 int SendData(void *pData,int len) 71 { 72 PutData(&g_iQin, &g_iQout, g_tArray,pData,sizeof(g_tArray),len); 73 return len; 74 } 75 76 int RecieveData(void) 77 { 78 GetData(&g_iQin, &g_iQout, g_tArray, tx_buf,sizeof(g_tArray),sizeof(DATA_T)); 79 return 0; 80 } 81 82 unsigned char MakeCheckSum(DATA_T *pData) 83 { 84 unsigned char ucCheckSum = 0; 85 unsigned char ucTmp; 86 unsigned char *pWork = (unsigned char *)pData; 87 88 for(ucTmp=0;ucTmp<pData->len;ucTmp++){ 89 ucCheckSum += pWork[ucTmp]; 90 } 91 92 ucCheckSum = ~ucCheckSum; 93 ucCheckSum++; 94 95 return ucCheckSum; 96 } 97 static int MkSlaveWithData(DATA_T *pReq, DATA_T *pRes,unsigned char type ,unsigned char*pdata, int datalen) 98 { 99 pRes->hid = pReq->hid; 100 pRes->cid = pReq->cid; 101 pRes->type = type; 102 pRes->len = sizeof(DATA_T) - MAX_DATA_SIZE + datalen; 103 pRes->chksum = 0; 104 pRes->seq = pReq->seq; 105 memcpy(pRes->userData, pdata, datalen); 106 107 pRes->checksum = MakeCheckSum(pRes); 108 109 return pRes->len; 110 111 } 112 113 int DataProcess(ITEM_MSG_T * pMsg) 114 { 115 DATA_T tmp_data; 116 DATA_T res_data; 117 DATA_INFO_T info; 118 119 memcpy(&tmp_data,pMsg->arBuf,sizeof(DATA_T)); 120 if (pMsg->type == RECV_PORT1_DATA) 121 { 122 if (tmp_data.type == GET_BD_INFO_REQ) 123 { 124 memset(&info,0,sizeof(DATA_INFO_T)); 125 info.version = 100; 126 info.channel = 96; 127 MkSlaveWithData(tmp_data,res_data,GET_BD_INFO_RES,(unsigned char*) &info,sizeof(DATA_INFO_T)); 128 SendData(&res_data, sizeof(DATA_T)); // 发送到环形队列 129 } 130 } 131 }
<3>创建example2.c文件
1 #define MAX_MSG_DATA_LEN (128) 2 3 typedef struct MSG_QUEUE_ITEM_T // 队列项数据结构定义 4 { 5 int len; 6 unsigned char data[MAX_MSG_DATA_LEN]; //队列项的大小128 7 }MSG_QUEUE_ITEM_T; 8 9 #define MSG_QUE_SIZE_MAX (6) //4 10 11 typedef struct ID_TBL_ITEM_T // 列表项数据结构定义 12 { 13 int used; 14 unsigned long id; 15 int head; 16 int tail; 17 MSG_QUEUE_ITEM_T queue[MSG_QUE_SIZE_MAX]; //列表项中定义一个队列,大小为6 18 }ID_TBL_ITEM_T; 19 20 #define ID_TBL_SIZE (2) // 列表大小为2 21 ID_TBL_ITEM_T g_IdTbl[ID_TBL_SIZE]; // 定义一个列表 22 23 24 int id_tbl_init(void) 25 { 26 int i; 27 for (i=0; i<ID_TBL_SIZE; i++) 28 { 29 g_IdTbl[i].used = 0; 30 } 31 return 0; 32 } 33 34 #if 0 35 int add_id_to_tbl(unsigned long id) 36 { 37 int i; 38 for (i=0; i<ID_TBL_SIZE; i++) 39 { 40 if (g_IdTbl[i].used == 1) 41 { 42 if ((g_IdTbl[i].id == id) 43 { 44 return 0; 45 } 46 } 47 } 48 49 for (i=0; i<ID_TBL_SIZE; i++) 50 { 51 if (g_IdTbl[i].used == 0) 52 { 53 g_IdTbl[i].used = 1; 54 g_IdTbl[i].id = id; 55 g_IdTbl[i].head = 0; 56 g_IdTbl[i].tail = 0; 57 58 return 1; 59 } 60 } 61 62 return 0; 63 } 64 #endif 65 66 int add_id_to_tbl(unsigned long id) 67 { 68 int i; 69 for (i=0; i<ID_TBL_SIZE; i++) 70 { 71 if (g_IdTbl[i].used == 1) 72 { 73 if ((g_IdTbl[i].id == id) 74 { 75 return 0; 76 } 77 } 78 else 79 { 80 g_IdTbl[i].used = 1; 81 g_IdTbl[i].id = id; 82 g_IdTbl[i].head = 0; 83 g_IdTbl[i].tail = 0; 84 return 1; 85 } 86 } 87 if (i >= ID_TBL_SIZE) 88 { 89 printf("id tbl overflow!!!\r\n"); 90 } 91 return 0; 92 } 93 94 int del_id_from_tbl(unsigned long id) 95 { 96 int i; 97 for (i=0; i<ID_TBL_SIZE; i++) 98 { 99 if (g_IdTbl[i].used == 1) 100 { 101 if ((g_IdTbl[i].id == id) 102 { 103 g_IdTbl[i].used = 0; 104 return 1; 105 } 106 } 107 } 108 printf("don't find id!!!\r\n"); 109 return 0; 110 } 111 112 int get_tbl_index(unsigned long id) 113 { 114 int i; 115 for (i=0; i<ID_TBL_SIZE; i++) 116 { 117 if (g_IdTbl[i].used == 1) 118 { 119 if ((g_IdTbl[i].id == id) 120 { 121 return i; 122 } 123 } 124 } 125 printf("don't find index!!!\r\n"); 126 return ID_TBL_SIZE; 127 } 128 129 int put_send_data_to_queue(unsigned long id , unsigned char *data, int len) 130 { 131 int indx; 132 ID_TBL_ITEM_T * pListItem; 133 MSG_QUEUE_ITEM_T QueItem; 134 indx = get_tbl_index(id ); 135 if (indx == ID_TBL_SIZE) 136 { 137 return 0; 138 } 139 memset(&QueItem,0,sizeof(MSG_QUEUE_ITEM_T)); 140 QueItem.len = len; 141 memcpy(QueItem.data,data,len); 142 143 pListItem =& g_IdTbl[indx]; 144 145 return PutData(&pListItem->head, &pListItem->tail ,pListItem->queue, &QueItem ,MSG_QUE_SIZE_MAX ,sizeof(MSG_QUEUE_ITEM_T)) 146 147 } 148 149 int get_send_data_from_queue(int idx, MSG_QUEUE_ITEM_T* pQueItem) 150 { 151 ID_TBL_ITEM_T * pListItem; 152 153 pListItem = g_IdTbl[idx]; 154 return GetData(&pListItem->head, &pListItem->tail ,pListItem->queue, void *pQueItem,MSG_QUE_SIZE_MAX,sizeof(MSG_QUEUE_ITEM_T)); 155 156 }