嵌入式不定长的任务消息传递组件的实现

Posted 沉默的小宇宙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式不定长的任务消息传递组件的实现相关的知识,希望对你有一定的参考价值。

通常如果上操作系统,这个组件便是现成的,但是很多小型系统未必都跑系统。很多软件定时器等结构也可以满足功能的模块化。不同的模块处理不同的任务,这时候任务或者是模块之间的协同、通信等就需要一套机制。下面直接上代码然后再做简要说明:


#define memory_zalloc malloc
#define memory_free free
#define memory_copy memcpy

typedef struct

    void *msg;
    int msgLen;
MSG_T,*PMSG_T;

struct MsgNode

    MSG_T struMsg;
    struct MsgNode* next;
;

struct MsgQueue

    struct MsgNode* head;
    struct MsgNode* tail;
    int size; /* 当前消息数量 */
    int max;    /* 最大消息数量 */
    int dir;    /* 消息存储方向 0:尾插,1:头插 */
;

//创建一个消息队列
struct MsgQueue* creat_msg_queue(int max, int dir)

    struct MsgQueue* newQueue = (struct MsgQueue*)memory_zalloc(sizeof(struct MsgQueue));
    if(!newQueue) 
    
        memory_free(newQueue);
        return 0;
    
    newQueue->head = NULL;
    newQueue->tail = NULL;
    newQueue->size = 0;
    newQueue->max = max;
    newQueue->dir = dir ? 1 : 0;
    return newQueue;


//创建一条消息
static struct MsgNode* creat_msg_node(void *msg,int len)

    struct MsgNode* newMsgNode;
    if(!msg || !len) return 0;
    newMsgNode = (struct MsgNode*)memory_zalloc(sizeof(struct MsgNode));
    if(!newMsgNode) 
    
        memory_free(newMsgNode);
        return 0;
    
    newMsgNode->struMsg.msg = (void *)memory_zalloc(len+1);// 字符串最后有一个零
    if(!newMsgNode->struMsg.msg) 
    
        memory_free(newMsgNode->struMsg.msg);
        memory_free(newMsgNode);
        return 0;
    
    memory_copy(newMsgNode->struMsg.msg, msg,len);
    newMsgNode->struMsg.msgLen = len;
    newMsgNode->next = NULL;
    return newMsgNode;


//入队
int push_msg(struct MsgQueue* pMsgQueue, void *msg,int len)
 
    struct MsgNode *newMsgNode;
    if(!pMsgQueue || !msg || !len) return -1;
    if(pMsgQueue->size >= pMsgQueue->max)
    
        printf("入队失败,队列满了!\\n");
        return -2;
    
    //创建一个新节点
    newMsgNode = creat_msg_node(msg, len);
    if(!newMsgNode) return -3;
    if(0 == pMsgQueue->size)    //队列为空
    
        pMsgQueue->tail = pMsgQueue->head = newMsgNode;//尾指针和头指针指向本节点
    
    else
    
        if(pMsgQueue->dir)/* 头插 */
        
            newMsgNode->next = pMsgQueue->head; //新节点next指向当前对头节点
            pMsgQueue->head = newMsgNode;// 对头指针指向新节点
        
        else/* 尾插 */
        
            pMsgQueue->tail->next = newMsgNode;//队尾结点next指向新节点
            pMsgQueue->tail = newMsgNode;//队尾指针指向新节点
        
    
    pMsgQueue->size++;
    return 0;


//出队
int pop_msg(struct MsgQueue* pMsgQueue, void** pMsg)

    int msgLen = 0;
    struct MsgNode* nextMsgNode;
    if(!pMsgQueue) return -1;
    
    if(0 == pMsgQueue->size)
    
        printf("出队失败,队列为空!\\n");
        return 0;
    
    else
    
        nextMsgNode = pMsgQueue->head->next;//定义一个指针,指向头结点的下一个结点
        msgLen = pMsgQueue->head->struMsg.msgLen;
        *pMsg = (void *)memory_zalloc(msgLen+1); // 字符串后面加0
        memset(*pMsg,0,msgLen+1);
        memory_copy(*pMsg,pMsgQueue->head->struMsg.msg,msgLen);
        memory_free(pMsgQueue->head->struMsg.msg);//释放消息空间
        memory_free(pMsgQueue->head);//释放头结点的空间
        pMsgQueue->head = nextMsgNode;//将头指针指向新的队首结点
        pMsgQueue->size--;
    
    return msgLen;


// 清除所有消息
int clear_msg_queue ( struct MsgQueue* pMsgQueue )

    struct MsgNode* nextMsgNode;
    if ( !pMsgQueue )
    
        return -1;
    
    while(pMsgQueue->size)
    
        nextMsgNode = pMsgQueue->head->next;//定义一个指针,指向头结点的下一个结点
        memory_free(pMsgQueue->head->struMsg.msg);
        memory_free(pMsgQueue->head);//释放头结点的空间
        pMsgQueue->head = nextMsgNode;//将头指针指向新的队首结点
        pMsgQueue->size--;
    
    return 0;


// 释放消息
int delect_msg_queue ( struct MsgQueue* pMsgQueue )

    if ( !pMsgQueue )
    
        return -1;
    
    clear_msg_queue(pMsgQueue);
    memory_free ( pMsgQueue );
    return 0;

测试:代码

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
char *message[5] = 

    "111","2222","33333","444444","5555555",
;
void main(void *args )

    int i,j;
    int res;
    void *msg;
    struct MsgQueue* kkQueue;
    printf("1. create msg_queue\\n");
    kkQueue = creat_msg_queue(16, 1);

    printf("2. push msg\\n");

    for(j=0;j<5;j++)
        for(i=0;i<5;i++)
        
            printf("        ");
            res = push_msg(kkQueue, message[i], strlen(message[i]));
            if(0 == res) printf("---> push msg[%s], len[%d], res[%d]\\n", message[i], strlen(message[i]), res);
            else printf("\\n");
        
    
    printf("3. pop msg\\n");
    for(j=0;j<5;j++)
        for(i=0;i<5;i++)
        
            printf("        ");
            res = pop_msg(kkQueue, &msg);
            if(res >0)
            
                printf("---> pos msg[%s], len[%d]\\n", msg, res);
                memory_free(msg);
                msg = 0;
            
        
        
    delect_msg_queue();    
    while(1)
    
    

效果如下:

1. create msg_queue
2. push msg
        ---> push msg[111], len[3], res[0]
        ---> push msg[2222], len[4], res[0]
        ---> push msg[33333], len[5], res[0]
        ---> push msg[444444], len[6], res[0]
        ---> push msg[5555555], len[7], res[0]
        ---> push msg[111], len[3], res[0]
        ---> push msg[2222], len[4], res[0]
        ---> push msg[33333], len[5], res[0]
        ---> push msg[444444], len[6], res[0]
        ---> push msg[5555555], len[7], res[0]
        ---> push msg[111], len[3], res[0]
        ---> push msg[2222], len[4], res[0]
        ---> push msg[33333], len[5], res[0]
        ---> push msg[444444], len[6], res[0]
        ---> push msg[5555555], len[7], res[0]
        ---> push msg[111], len[3], res[0]
        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

        入队失败,队列满了!

3. pop msg
        ---> pos msg[111], len[3]
        ---> pos msg[5555555], len[7]
        ---> pos msg[444444], len[6]
        ---> pos msg[33333], len[5]
        ---> pos msg[2222], len[4]
        ---> pos msg[111], len[3]
        ---> pos msg[5555555], len[7]
        ---> pos msg[444444], len[6]
        ---> pos msg[33333], len[5]
        ---> pos msg[2222], len[4]
        ---> pos msg[111], len[3]
        ---> pos msg[5555555], len[7]
        ---> pos msg[444444], len[6]
        ---> pos msg[33333], len[5]
        ---> pos msg[2222], len[4]
        ---> pos msg[111], len[3]
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!
        出队失败,队列为空!

该方法主要采用线性表及队列结构,外加动态内存管理的方式组成。创建的时候可以选择头插法及尾插法,头插法可以理解为最新的消息优先处理。尾插法则相反,消息必须先入先出,满足队列的特性,这样可以保障先到的消息必须要按顺序一个个处理,后到的消息若空间不够则视为丢弃。

使用注意:使用pop接口获取消息后,处理完需要做内存释放动作。

By Urien 2023/02/24

以上是关于嵌入式不定长的任务消息传递组件的实现的主要内容,如果未能解决你的问题,请参考以下文章

STM32 | 串口空闲中断接收不定长数据(DMA方式)

文本分类

尝试在 Nuxt 中将数据从组件传递到页面时出现错误消息

51单片机上实时多任务操作系统-教程

命名管道(C#)

flexible array柔性数组不定长的数据结构Struct详解