【UCOSIII源码阅读笔记】第一篇

消息队列相关设计架构

消息队列使用方式

创建消息队列:

OS_Q queue;                             //声明消息队列

/* 创建消息队列 queue */
OSQCreate ((OS_Q         *)&queue,            //指向消息队列的指针
           (CPU_CHAR     *)"Queue For Test",  //队列的名字
           (OS_MSG_QTY    )20,                //最多可存放消息的数目
           (OS_ERR       *)&err);             //返回错误类型

发布消息队列:

/* 发布消息到消息队列 queue */
OSQPost ((OS_Q        *)&queue,                            //消息变量指针
         (void        *)"Fire uC/OS-123",                //要发送的数据的指针,将内存块首地址通过队列“发送出去”
         (OS_MSG_SIZE  )sizeof ( "Fire uC/OS-123" ),     //数据字节大小
         (OS_OPT       )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
         (OS_ERR      *)&err);	                            //返回错误类型

其中的(void *)"Fire uC/OS-123"表示指向字符串的指针。
请求消息:

/* 请求消息队列 queue 的消息 */
pMsg = OSQPend ((OS_Q         *)&queue,                //消息变量指针
                (OS_TICK       )0,                     //等待时长为无限
                (OS_OPT        )OS_OPT_PEND_BLOCKING,  //如果没有获取到信号量就等待
                (OS_MSG_SIZE  *)&msg_size,             //获取消息的字节大小
                (CPU_TS       *)0,                     //获取任务发送时的时间戳
                (OS_ERR       *)&err);                 //返回错误
      
printf ( "\r\n接收消息的长度:%d字节,内容:%s\r\n", msg_size, pMsg );

架构分析

声明的消息队列OS_Q 的结构体内容如下:
在这里插入图片描述
其中包括PendListMsgQ两个重要的结构体。
PendList用于在某个任务想要从OS_Q 中获取消息消息时,如果OS_Q 为空,则该任务被插入到PendList中排队,等待OS_Q 中消息的到来;当某个任务想要向OS_Q 发布消息时,如果看到这个OS_Q PendList中有任务在排队等待,则直接把消息给正在排队的任务。
MsgQ用于在某个任务想要向OS_Q 发布消息时,如果当前没有任务在这个OS_Q 上排队等消息,那么它就会把消息放到OS_Q MsgQ中;当某个任务想要从OS_Q 获取消息时,如果它发现OS_Q MsgQ中有消息,那么就直接从MsgQ中取走消息。
整个过程类似于学生去食堂买饭,食堂就是OS_Q ,学生排队区就是PendList,食品摆放区就是MsgQ,当一个学生来到看食品摆放区有食物时,他就直接拿走,没有就去排队区排队,当上饭阿姨上饭时发现有学生正在排队,阿姨就直接把饭给他,如果没有学生排队就把饭放在食品摆放区,等学生来拿。
ucosiii中消息队列的代码实现在os_q.c文件中,以发布消息为例,函数调用过程如下:
在这里插入图片描述
消息队列发布消息被分成3层,OSQPost()用于用户调用,主要对用户传入参数的正确性进行判断,OS_QPost()用于判断把消息放到MsgQ中还是直接给PendList中正在等待消息的任务,OS_MsgQPut()用于从消息池中取出一个消息,把他包装一下(设置一下消息指针、消息大小、消息时间戳)放到MsgQOS_Post()用于把消息给在PendList中等待的任务,并且将其从PendList中移除、唤醒。
MsgQ有关的操作函数都封装在os_msg.c中,其中包括以下函数:
OS_MsgPoolInit():初始化消息池;
OS_MsgQFreeAll():把一个MsgQ上的所有消息放回到消息池中;
OS_MsgQInit():初始化MsgQ
OS_MsgQGet:从MsgQ中获取一个消息;
OS_MsgQPut:把一个消息放到MsgQ中。

编程技巧

1、os_msg.c中维护一个消息池和所有的MsgQ,消息池把空闲消息用链表串起来,MsgQ把一个OS_Q 中正在使用的消息用链表串起来,如果在自己的项目中有类似的资源管理方式需求,可以参考os_msg.c,对资源进行申请和回收。
2、消息池结构体如下:

struct  os_msg_pool {                                       /* OS_MSG POOL                                            */
    OS_MSG              *NextPtr;                           /* Pointer to next message                                */
    OS_MSG_QTY           NbrFree;                           /* Number of messages available from this pool            */
    OS_MSG_QTY           NbrUsed;                           /* Current number of messages used                        */
    OS_MSG_QTY           NbrUsedMax;                        /* Peak number of messages used                           */
};

这种以Nbr开头的变量表示某种数量的形式可以参考;
消息结构体如下:

struct  os_msg {                                            /* MESSAGE CONTROL BLOCK                                  */
    OS_MSG              *NextPtr;                           /* Pointer to next message                                */
    void                *MsgPtr;                            /* Actual message                                         */
    OS_MSG_SIZE          MsgSize;                           /* Size of the message (in # bytes)                       */
    CPU_TS               MsgTS;                             /* Time stamp of when message was sent                    */
};

TS表示时间(time stamp),这种变量命名可以参考。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值