一步一步教你使用uCOS-II( 八 )


如果如果任务调用(),信号量无效(为0),那么()调用()函数,把放入等待列表中 。(等待到什么时候呢?要看()(或者等待超时情况),由它释放信号量并检查任务执行权,见下资料)
◆() 发出(释放)一个信号量(注:由任务或中断操作)
本函数其中调用()函数,把优先级最高的任务(在这假如是,另外假设当前调用()的任务是)从等待任务列表中去除,并使它进入就绪态 。然后调用()进行任务调度 。如果是当前就绪态中优先级最高的任务,则内核执行;否则,()直接返回,继续执行 。
UCOS另类信号量--互斥信号量
在UCOS的信号量使用过程中,我们经常会用的是二值信号量,而在二值信号两种用的醉的情况就是互斥信号量 。互斥信号是本身是一种二进制信号,具有超出uCOS-II提供的一般信号机制的特性 。由于其特殊性,UCOS的作者将其独立成章,单独对待 。组织了一套对于互斥信号量管理的单独函数 。互斥信号量具有以下特点: 1) 降解优先级反转 。2) 实现对资源的独占式访问(二值信号量) 。
在应用程序中使用互斥信号是为了减少优先级翻转问题,当一个高优先级的任务需要的资源被一个低优先级的任务使用时,就会发生优先级翻转问题 。为了减少优先级翻转问题,内核可以提高的优先级任务的优先级,先于高优先级的任务运行,释放占用的资源 。
为了实现互斥,实时内核需要具有支持在同一优先级具有多个任务的能力 。不幸的是,UC/OS-II不允许在相同的优先级有多个任务,必须只有一个任务 。但是我们有另外的方法解决这个问题 。可以把需要资源的高优先级任务上面的一个任务使用Mutex保留,允许提高的优先级任务的优先级 。
举一个信号工作的例子,如l下面的程序所示 。
其中有三个任务可以使用共同的资源,为了访问这个资源,每个任务必须在互斥信号 上等待(pend),任务#1有最高优先级10,任务#2优先级为15,任务#3优先级为20,一个没有使用的正好在最高优先级之上的优先级#9用来作为优先级继承优先级 。如main()所示,代码中(1)进行uC/OS-II初始化,并通过调用()代码中(2)创建了一个互斥信号 。需要注意的是,()函数使用PIP最为参数 。然后创建三个任务代码中(3),启动uC/OS-II 代码中(4).
假设任务运行了一段时间,在某个时间点,任务#3最先访问了共同的资源,并得到了互斥信号,任务#3运行了一段时间后被任务#1抢占 。任务#1需要使用这个资源,并通过调用()企图获得互斥信号,这种情况下,()会发现一个高优先级的任务需要这个资源,就会把任务#3的优先级提高到9,同时强迫进行上下文切换退回到任务#3执行 。任务#3可以继续执行然后释放占用的共同资源 。任务#3通过调用()释放占用的mutex信号,()会发现mutex被一个优先级提升的低优先级的任务占有,就会把任务#3的优先级返回到20 。把资源释放给任务#1使用,执行上下文切换到任务#1
-----------------------------------------------------------------
*;
[1000];
[1000];
[1000];
void main (void)
INT8U err;
(); /* (1) */
/* ---------- 应用程序初始化 ---------- */
(9, &err); /* (2) */
(, (void *)0, &[999], 10); /* (3) */
(, (void *)0, &[999], 15);
(, (void *)0, &[999], 20);
/* -------------------- */
(); /* (4) */
void(void *pdata)
INT8U err;
pdata = http://www.kingceram.com/post/pdata;
while (1) {
/* --------- 应用程序代码 ---------- */
(, 0, &err);
/* ------- 访问贡献资源 ------ */
();
/* --------- 应用程序代码 ---------- */