ucos-II 任务间通信源码分析
2013-01-25 16:57
579 查看
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,等待事件或超时后运行;
当任务收到消息或超时,此时若收到消息返回消息,否则返回空指针(超时原因);
消息队列
消息队列全局变量
消息队列的主要函数分析
建立一个消息队列 OSQCreate,初始化一个EVENT变量和OS_Q,并将该OS_Q的地址赋值给EVENT的成员,如下
向消息队列中发送一个消息OSQPost (FIFO),函数处理如下:
调用OS_EventTaskRdy和OS_Sched, 将消息队列的等待任务队列中的一个任务唤醒;
在队头插入该消息;(疑问:为什么不是先插入队列再调度等待任务??)
等待消息队列中的消息 OSQPend,函数处理如下:
如果当前的消息队列中有消息,从队尾取出一个消息返回;
否则将当前任务的状态置为OS_STAT_Q,调用OS_EventTaskWait和OS_Sched挂起该任务;
当任务重新被调度到后,从OSTCBCur->OSTCBMsg取出消息(在Post函数中调用的OS_EventTaskRdy赋值的),返回该消息值;
备注:在代码中要注意的是,与消息邮箱相似XXPend函数的上下半段实际上不是一次调度到的,如下:
消息邮箱
消息邮箱主要函数分析:
建立一个邮箱 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);
相关文章推荐
- ucos-II 任务调度源码分析(一)
- ucos-II 任务间同步源码分析(二)
- ucos-II 任务调度源码分析(二)
- ucos-II 任务调度源码分析(三)
- ucos-II 任务间同步源码分析(一)
- UCOS_II学习笔记---任务管理之建立任务函数分析
- ucos-II 事件控制块源码分析
- UCOS-II任务间通信:邮箱
- uCOS-II任务间通信之信号量 [转载]
- 关于ARM架构下ucos2任务切换函数OSCtxSw源码分析
- uCOS-II任务间通信之信号量
- UCOS_II学习笔记---任务管理之删除任务函数分析
- UCOS_II学习笔记---任务管理之请求删除任务函数分析
- ucos II 任务间 通信之三:信号量
- uCOS-II任务间通信之邮箱 [转载]
- ucos II 任务间 通信之三:信号量
- uCOS-II任务间通信之全局变量 [转载]
- uCOS-II任务间通信之事件控制块 [转载]
- ucos-II 内存管理源码分析
- uCOS-II整理之任务的同步与通信