ucos-II 任务间通信源码分析

本文介绍了uCOS-II 2.0版本中的任务间通信机制,包括消息邮箱和消息队列两种方式。详细分析了消息邮箱的主要函数及其实现原理,并深入探讨了消息队列的数据结构和关键函数的工作流程。

ucos-II 2.0版本的任务间通信提供消息邮箱和消息队列两种机制,都基于内核的事件控制块机制实现。

消息邮箱

消息邮箱主要函数分析:

  • 建立一个邮箱 OSMboxCreate:初始化一个OS_EVENT_TYPE_MBOX类型的事件块;
  • 向邮箱发送一个消息 INT8U  OSMboxPost (OS_EVENT *pevent, void *msg),该函数调用OS_EventTaskRdy,在事件任务处理中将msg赋值给消息邮箱等待队列中优先级最高的任务。ptcb->OSTCBMsg       = msg;
  • 等待发送到邮箱的消息 OSMboxPend,处理如下:
    • 如果当前消息邮箱有消息则取出消息返回,此时msg就是函数的返回值;
    • 否则,当前任务状态设置为OS_STAT_MBOX,等待事件或超时后运行;
    • 当任务收到消息或超时,此时若收到消息返回消息,否则返回空指针(超时原因);

消息队列

消息队列全局变量

 

typedef struct os_q { /* QUEUE CONTROL BLOCK                                            */
    struct os_q   *OSQPtr; /* Link to next queue control block in list of free blocks     */
    void         **OSQStart; /* Pointer to start of queue data                           */
    void         **OSQEnd; /* Pointer to end   of queue data                              */
    void         **OSQIn; /* Pointer to where next message will be inserted  in   the Q  */
    void         **OSQOut; /* Pointer to where next message will be extracted from the Q  */
    INT16U         OSQSize; /* Size of queue (maximum number of entries) */
    INT16U         OSQEntries; /* Current number of entries in the queue */
} OS_Q;


typedef struct {
    void          *OSMsg; /* Pointer to next message to be extracted from queue  */
    INT16U         OSNMsgs; /* Number of messages in message queue  */
    INT16U         OSQSize; /* Size of message queue                                       */
    INT8U          OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur  */
    INT8U          OSEventGrp;  /* Group corresponding to tasks waiting for event to occur  */
} OS_Q_DATA;

 

 

OS_EXT  OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks    */
OS_EXT  OS_Q  OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks              */

 

消息队列的主要函数分析

 

  • 建立一个消息队列 OSQCreate,初始化一个EVENT变量和OS_Q,并将该OS_Q的地址赋值给EVENT的成员,如下
pq = OSQFreeList; 
...
pevent->OSEventPtr  = pq;
  • 向消息队列中发送一个消息OSQPost (FIFO),函数处理如下:
    • 调用OS_EventTaskRdy和OS_Sched, 将消息队列的等待任务队列中的一个任务唤醒;
    • 在队头插入该消息;(疑问:为什么不是先插入队列再调度等待任务??)
  • 等待消息队列中的消息 OSQPend,函数处理如下:
    • 如果当前的消息队列中有消息,从队尾取出一个消息返回;
    • 否则将当前任务的状态置为OS_STAT_Q,调用OS_EventTaskWait和OS_Sched挂起该任务;
    • 当任务重新被调度到后,从OSTCBCur->OSTCBMsg取出消息(在Post函数中调用的OS_EventTaskRdy赋值的),返回该消息值;

备注:在代码中要注意的是,与消息邮箱相似XXPend函数的上下半段实际上不是一次调度到的,如下:

 

    OSTCBCur->OSTCBStat |= OS_STAT_Q;  
    OSTCBCur->OSTCBDly   = timeout;              
    OS_EventTaskWait(pevent);                    
    OS_EXIT_CRITICAL();
    OS_Sched();                                  
    
    //**下面的函数是重新调度后执行的,此时或者消息队列里已经有消息或者等待超时。
    OS_ENTER_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;
    if (msg != (void *)0) {                     
        OSTCBCur->OSTCBMsg      = (void *)0;    
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; 
        OS_EXIT_CRITICAL();
        *err                    = OS_NO_ERR;
        return (msg);                            
    }
    OS_EventTO(pevent);                         
    OS_EXIT_CRITICAL();
    *err = OS_TIMEOUT;                           
    return ((void *)0);                          

 

转载于:https://www.cnblogs.com/Fredric-2013/archive/2013/01/25/2876992.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值