当前位置:   article > 正文

使用C 实现的 开源消息队列 cQueue

cqueue

概述

队列是一种非常好用的数据结构,消息队列可以提高业务逻辑的成功率,在Unix/Linux下,消息队列还是进程之间通信的一种技术方案,关于队列数据结构的知识点,可以参考之前的文章:
深入理解数据结构(一):队列

队列的功能虽然很好用,但是编写一个稳健的消息队列功能,还是有些难度的,本文参考uC/OS 操作系统的队列代码原理,编写了消息队列 功能。

使用时可以将cQueue.h和cQueue.c 包含到自己的工程代码中,调用API接口函数,即可实现消息队列的管理,具体的可以参考代码库中的example.c 。

由于定义的消息队列中的消息类型为 void 型,所以可以传入自定义的消息类型,比如自定义结构体。

代码库位置如下:
github : cQueue
gitee : cQueue

cQueue 说明

数据结构

cQueue using the cQueue struct data type:
  • 1
/*---------------The cQueue structure ------------------------------------------------------------*/
typedef struct cQueue{          
    void            **QMemory;  /* pointer to message queue storage area                          */                                   
    void            **QStart;   /* pointer to start of queue data                                 */
    void            **QEnd;     /* pointer to end   of queue data                                 */
    void            **QIn;      /* pointer to where next message will be inserted in the queue    */
    void            **QOut;     /* pointer to where next message will be extracted from the queue */
    int             QSize;      /* size of queue -- max number of entries                         */
    int             QEntries;   /* current number of entries in the queue                         */
} cQueue_t;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

API

/*
 * Description  :   创建并初始化1个队列结构                 
 * @para[in]    :   size    消息队列的大小,最多存放消息队列的条数
 * @return      :   消息队列指针
 */
cQueue_t *cQcreate(int size);

/*
 * Description  :   删除消息队列,并释放消息队列申请的内存区域
 * @para[in]    :   pq     消息队列指针
 * @return      :   NULL
 */
void cQDelete(cQueue_t *pq);

/*
 * Description  :  清空消息队列
 * @para[in]    :   pq      消息队列指针
 * @return      :   NULL
 */
void cQFlush(cQueue_t *pq);

/*
 * Description  :   从消息队列中接收消息
 * @para[in]    :   pq       消息队列指针
 * @para[out]   :   perr    接收消息错误标志,0-无;1-消息队列为空。
 * @return      :   接收到的消息指针
 */
void *cQRcv(cQueue_t *pq, char *perr);

/*
 * Description  :   向消息队列中发送消息
 * @para[in]    :   pq      消息队列指针
 * @para[in]    :   pmsg    要发送的消息指针
 * @return      :   ERR_Q_NONE      发送成功
 *                  ERR_Q_FULL      发送失败,当前消息队列已满
 */
int cQPost(cQueue_t *pq, void *pmsg);

/*
 * Description  :   向消息队列头部发送消息,使用该发送功能,允许发送优先级高的消息,相当于
 *                   在最前面插入消息,这样下次读取消息队列时,读到的是刚刚发送的这条消息。
 * 
 * @para[in]    :   pq      消息队列指针
 * @para[in]    :   pmsg    要发送的消息指针
 * 
 * @return      :   ERR_Q_NONE     发送成功
 *                  ERR_Q_FULL     发送失败,当前消息队列已满。
 */
int cQPostFront(cQueue_t *pq, void *pmsg);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

程序实例

#include <stdio.h>
#include <stdlib.h>
#include "cQueue.h" 

int main(int argc, char *argv[]) {
	int i,j;
	int *pmsg;
	char perr;
	cQueue_t *pq;
	int *prx;
	/* 创建1个长度为110的消息队列 */
	pq = cQcreate(110);
	
    /* cQPost ...*/		
	for(i = 0; i < 100; i++){
		pmsg = (int *)malloc(10*sizeof(int));
		for(j = 0; j < 10; j++){
			pmsg[j] = i*10 + j;
		}
		cQPost(pq, (void *)pmsg);
	}
	
	/* cQPostFront...*/
	pmsg = (int *)malloc(10*sizeof(int));
	for(j = 0; j < 10; j++){
		pmsg[j] = 1000 + j;
	}
	cQPostFront(pq, (void *)pmsg);
	
	/* cQRcv...*/
	for(j = 0; j < 101; j++){
		prx = (int *)cQRcv(pq, &perr);
		printf("prx%3d:", j);
		for(i = 0; i < 10; i++){
			printf("<%4d>", prx[i]);
		}
		printf("\n");
	}
	/*  删除消息队列 */
	cQDelete(pq);
	
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

注意

1、cQueue的实现没有考虑到消息队列的读/写限制,在使用过程中,如果业务逻辑涉及到对消息队列访问的“同步/互斥”,还是要结合具体的使用环境来添加“同步/互斥”条件。
2、为了兼容性,cQueue中消息的类型均为void,所以向消息队列插入消息时,强制转换为(void *),而读取消息时,则要进行显性的转换,转换成我们自定义的消息类型。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/908164
推荐阅读
相关标签
  

闽ICP备14008679号