一: 互斥型信号量的理解
互斥型信号量首先是二值信号量,实现对共享资源的独占式处理,其次互斥型信号量可以在应用程序代码中用于降解优先级的反转问题,这个是它和普通信号量的最本质的区别。
二: 优先级反转的问题
假设现在有三个任务分别是Task1,Task2,Task3,优先级从大到小。程序在运行过程中,Task1和Task2处于挂起(pend)的状态,等待某个事件的发生。这样优先级最低的Task3首先申请到了mutex并开始同共享资源打交道,过了一会儿,Task1等待的事件出现了,那么此时Task1就需要使用共享资源了,于是申请mutex(OSMutexPend)。在这种情况下,OSMutexPend注意到高优先级的任务要使用这个共享资源,于是将Task3的优先级升到比Task1更高的级别,并强制任务调度回到Task3。而Task1只好继续挂起,等待共享资源被释放。同时Task3继续运行,直到Task3调用OSMutexPost(),释放Mutex.在调用OSMutexPost()时,OSMutexPost()会将Task3的优先级恢复到原来的水平,同时还会注意到有个高优先级的任务Task1需要这个Mutex,于是将这个Mutex交给Task1,并做任务切换。
三:uc/os-ii的互斥型信号量由三个部分组成:
◆一个标志,指示mutex是否可以使用(0或1)
◆一个优先级,准备一旦高优先级的任务需要这个mutex,赋予给占有mutex的任务。
◆一个等待该mutex的任务列表
四:程序示例:
Void main (void)
{
OSInit();
**************应用程序初始化**********************
OSMutexCreate(9,&err);
OSTaskCreate(TaskPrio10,(void *)0,&TaskPrio10Stk[999],10);
OSTaskCreate(TaskPrio15,(void *)0,&TaskPrio15Stk[999],15);
OSTaskCreate(TaskPrio20,(void *)0,&TaskPrio20Stk[999],20);
**************应用程序初始化************************
OSStart();
}
Void TaskPrio10 (void * pdata)
{
While(1){
*************应用程序代码***********************
OSMutexPend(ResouceMutex,0,&err);
*************占用共享资源***********************
OSMutexPost(ResouceMutex);
*************应用程序代码***********************
}
}
Void TaskPrio15 (void * pdata)
{
While(1){
*************应用程序代码***********************
OSMutexPend(ResouceMutex,0,&err);
*************占用共享资源***********************
OSMutexPost(ResouceMutex);
*************应用程序代码***********************
}
}
Void TaskPrio20 (void * pdata)
{
While(1){
*************应用程序代码***********************
OSMutexPend(ResouceMutex,0,&err);
*************占用共享资源***********************
OSMutexPost(ResouceMutex);
*************应用程序代码***********************
}
}
五,三个重要函数的应用
1. OSMutexCreate (INT8U prio, INT8U *err)
Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In other words, when the semaphore is acquired and a higher priority task attempts to obtain the semaphore then the priority of the task owning the semaphore is raised to this priority. It is assumed that you will specify a priority that is LOWER in value than ANY of the tasks competing for the mutex.
err is a pointer to an error code which will be returned to your application:
OS_NO_ERR if the call was successful.
OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an ISR
OS_PRIO_EXIST if a task at the priority inheritance priority already exist.
OS_ERR_PEVENT_NULL No more event control blocks available.
OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed (i.e. > OS_LOWEST_PRIO)
Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the created mutex.
== (void *)0 if an error is detected.
2. OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
Arguments : pevent is a pointer to the event control block associated with the desired mutex.
Returns : none
2. OSMutexPost (OS_EVENT *pevent)
Arguments : pevent is a pointer to the event control block associated with the desired mutex.