互斥条件
实现任务间通讯最简便到办法是使用共享数据结构。。虽然共享数据区法简化了任务间的信息交换,但是必须保证每个任务在处理共享数据时的排它性,以避免竞争和数据的破坏。与共享资源打交道时,使之满足互斥条件最一般的方法有:
- 关中断
- 使用测试并置位指令
- 禁止做任务切换
- 利用信号量
关中断和开中断
处理共享数据时保证互斥,最简便快捷的办法是关中断和开中断。
Disable interrupts; /*关中断*/ |
Access the resource (read/write from/to variables); /*读/写变量*/ |
Reenable interrupts; /*重新允许中断*/
|
μC/OS-Ⅱ在处理内部变量和数据结构时就是使用的这种手段,即使不是全部,也是绝大部分。实际上μC/OS-Ⅱ提供两个宏调用,允许用户在应用程序的C代码中关中断然后再开中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()
void Function (void) |
{ |
OS_ENTER_CRITICAL(); |
. |
. /*在这里处理共享数据*/ |
. |
OS_EXIT_CRITICAL(); |
} |
可是,必须十分小心,关中断的时间不能太长。因为它影响整个系统的中断响应时间,即中断延迟时间。。这也是在中断服务子程序中处理共享变量或共享数据结构的唯一方法。在任何情况下,关中断的时间都要尽量短。
如果使用某种实时内核,一般地说,关中断的最长时间不超过内核本身的关中断时间,就不会影响系统中断延迟。
测试并置位
如果不使用实时内核,当两个任务共享一个资源时,一定要约定好,先测试某一全程变量,如果该变量是0,允许该任务与共享资源打交道。为防止另一任务也要使用该资源,前者只要简单地将全程变量置为1,这通常称作测试并置位(Test-And-Set),或称作TAS。TAS操作可能是微处理器的单独一条不会被中断的指令,或者是在程序中关中断做TAS操作再开中断。
Disable interrupts; 关中断 |
if (‘Access Variable’ is 0) { 如果资源不可用,标志为0 |
Set variable to 1; 置资源不可用,标志为1 |
Reenable interrupts; 重开中断 |
Access the resource; 处理该资源 |
Disable interrupts; 关中断 |
Set the ‘Access Variable’ back to 0; 清资源不可使用,标志为0 |
Reenable interrupts; 重新开中断 |
} else { 否则 |
Reenable interrupts; 开中断 |
/* You don’t have access to the resource, try back later; */ /* 资源不可使用,以后再试; */ |
} |
禁止,然后允许任务切换
如果任务不与中断服务子程序共享变量或数据结构,可以使用禁止、然后允许任务切换。以μC/OS-Ⅱ的使用为例,两个或两个以上的任务可以共享数据而不发生竞争。注意,此时虽然任务切换是禁止了,但中断还是开着的。如果这时中断来了,中断服务子程序会在这一临界区内立即执行。中断服务子程序结束时,尽管有优先级高的任务已经进入就绪态,内核还是返回到原来被中断了的任务。直到执行完给任务切换开锁函数OSSchedUnlock (),内核再看有没有优先级更高的任务被中断服务子程序激活而进入就绪态,如果有,则做任务切换。虽然这种方法是可行的,但应该尽量避免禁止任务切换之类操作,因为内核最主要的功能就是做任务的调度与协调。禁止任务切换显然与内核的初衷相违。应该使用下述方法。
void Function (void) |
{ |
OSSchedLock(); |
. |
. /* You can access shared data in here (interrupts are recognized) */ |
. /*在这里处理共享数据(中断是开着的)*/ |
OSSchedUnlock(); |
} |
UCOS_II基础入门:
扫一扫关注微信公众号,获取更多实时的嵌入式资讯,嵌入式学习指导方法,汽车电子最新资讯等。。