您的位置:首页 > 其它

ucos-II 任务间同步源码分析(一)

2013-01-25 11:39 323 查看
ucos-II 任务间的同步主要有三个部分,信号量、互斥性信号量和事件标志组,前两者都基于事件机制完成(见ucos-II 事件控制块)。本文主要记录信号量和互斥信号量的分析。

1. 信号量SEM的主要接口函数

建立一个信号量:OS_EVENT *OSSemCreate(INT16U cnt);创建一个OS_EVENT_TYPE_SEM类型的事件块,将cnt赋值给OSEventCnt,可表示共享资源的数量;

删除一个信号量:OSSemDel();在删除一个信号量时需要考虑当前是否有任务因为该信号量而挂起,此时有两种删除方式,一种是OS_DEL_NO_PEND,它要求删除该信号量时没有任务因为该信号量被挂起,否则会返回错误;另外一种是OS_DEL_ALWAYS,这个时候信号量一定被删除,但删除前所有的等待任务都会被加入就绪队列,如下:

case OS_DEL_ALWAYS: /* Always delete the semaphore              */
while (pevent->OSEventGrp != 0u) {  /* Ready ALL tasks waiting for semaphore    */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
}


等待一个信号量:OSSemPend():首先判断当前的信号量是否存在(if(pevent -> OSEventCnt > 0)),如果存在则减去一个资源量返回;否则调用该函数的任务将置状态为OS_STAT_SEM,调用OS_EventTaskWait和OS_Sched后进入等待状态。

发出一个信号量:OSSemPost();通过EVENT机制,选择等待该信号量的优先级最高的任务进入就绪队列并调度;信号量增加 pevent -> OSEventCnt ++;

2. 互斥信号量(Mutex)的主要接口函数

mutex的目的在于解决共享资源的独占处理,为了解决该共享过程中的优先级翻转问题。mutex是所有任务间同步、通信手段中唯一不采用改变任务状态(挂起),而是通过调整任务优先级的形式触发调度。

建立一个mutex OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err); mutex在创建时需要赋给一个优先级,函数处理如下:删除一个mutex,OSMutexDel(),该函数的机制与OSSemDel几乎一模一样,此处不做赘述;

确认该mutex的优先级是唯一的,不存在任务已经占用该优先级;否则返回错误;

更新OSTCBPrioTbl相应位,表示该优先级已被占用;

建立一个OS_EVNET_TYPE_MUTEX的事件;并在OSEventCnt中保存这个优先级(高8位保存优先级,低8位保存mutex有效标志);

pevent->OSEventType    = OS_EVENT_TYPE_MUTEX;
pevent->OSEventCnt     = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail.  */
pevent->OSEventPtr     = (void *)0;


等待一个mutex挂起:OSMutexPend(), 函数处理如下:

如果当前mutex有效,即未被占用,则 1.置该mutex为无效;2.在OSEventCnt中保存当前任务的优先级;3.在mutex的OSEventPtr中保存当前任务的TCB地址;否则

获取mutex的优先级,如果当前任务的优先级小与占用该mutex任务的优先级,则该任务的优先级被设置为mutex的优先级并挂起;

释放一个互斥信号量 OSMutexPost(),函数处理如下:

如果当前任务的优先级等于mutex的优先级(即在上次OSMutexPend时被提升了优先级),则恢复该任务原本优先级;

若当前存在等待该mutex的任务则调用OS_EventTaskRdy和OS_Sched唤醒;

例子:优先级反转的情况,低优先级占用mutex后,被中优先级抢断挂起,高优先级需要mutex则必须等待中优先级任务结束。在ucos-II 中 高优先级需要mutex时,即调用OSMutexPend时,原本占用mutex的低优先级任务会调整优先级至mutex的优先级。然后再OSMutexPost时再把优先级调整回原来的优先级。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: