μC/OS-II的任务之间的通讯与同步
.8(2)]。最后,从任务控制块中将指向事件控制块的指针删除[L6.8(3)]。用户应当注意,调用OSEventTO()也应当先关中断。
程序清单L6.8因为等待超时将任务置为就绪状态
voidOSEventTO(OS_EVENT*pevent)
{
if((pevent->OSEventTbl[OSTCBCur->OSTCBY]=~OSTCBCur->OSTCBBitX) ==0)
{ (1)
pevent->OSEventGrp=~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBStat=OS_STAT_RDY;(2)
OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(3)
}
6.6 信号量
μC/OS-II中的信号量由两部分组成:一个是信号量的计数值,它是一个16位的无符号整数 (0到65,535之间) ; 另一个是由等待该信号量的任务组成的等待任务表。 用户要在OS_CFG.H中将OS_SEM_EN开关量常数置成1,这样μC/OS-II才能支持信号量。
在使用一个信号量之前, 首先要建立该信号量, 也即调用OSSemCreate()函数(见下一节) ,
对信号量的初始计数值赋值。该初始值为0到65,535之间的一个数。如果信号量是用来表示一个或者多个事件的发生, 那么该信号量的初始值应设为0。 如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1(例如,把它当作二值信号量使用)。最后,如果该信号量是用来表示允许任务访问n个相同的资源,那么该初始值显然应该是n,并把该信号量作为一个可计数的信号量使用。
μC/OS-II提供了5个对信号量进行操作的函数。它们是:OSSemCreate(),OSSemPend(),
OSSemPost(),OSSemAccept()和OSSemQuery()函数。图F6.5说明了任务、中断服务子程序和
信号量之间的关系。图中用钥匙或者旗帜的符号来表示信号量:如果信号量用于对共享资源的
访问,那么信号量就用钥匙符号。符号旁边的数字N代表可用资源数。对于二值信号量,该值
就是1;如果信号量用于表示某事件的发生,那么就用旗帜符号。这时的数字N代表事件已经发
生的次数。从图F6.5中可以看出OSSemPost()函数可以由任务或者中断服务子程序调用,而
OSSemPend()和OSSemQuery()函数只能有任务程序调用。

图F6.5任务、中断服务子程序和信号量之间的关系——Figure6.5
6.6.1 建立一个信号量,OSSemCreate()
程序清单L6.9是OSSemCreate()函数的源代码。首先,它从空闲任务控制块链表中得到一个事件控制块[L6.9(1)],并对空闲事件控制链表的指针进行适当的调整,使它指向下一个空闲的事件控制块[L6.9(2)]。如果这时有任务控制块可用[L6.9(3)],就将该任务控制块的事件类型设置成信号量OS_EVENT_TYPE_SEM[L6.9(4)]。其它的信号量操作函数OSSem???()通过检查该域来保证所操作的任务控制块类型的正确。例如,这可以防止调用OSSemPost()函数对一个用作邮箱的任务控制块进行操作[6.06节,邮箱]。接着,用信号量的初始值对任务控制块进行初始化[L6.9(5)],并调用 OSEventWaitListInit()函数对事件控制任务控制块的等待任务列表进行初始化[见6.01节,初始化一个任务控制块,OSEventWaitListInit()][L6.9(6)]。因为信号量正在被初始化,所以这时没有任何任务等待该信号量。最后,OSSemCreate()返回给调用函数一个指向任务控制块的指针。以后对信号量的所有操作,如OSSemPend(),OSSemPost(),OSSemAccept()和OSSemQuery()都是通过该指针完成的。因此,这个指针实际上就是该信号量的句柄。如果系统中没有可用的任务控制块,OSSemCreate()将返回一个NULL指针。
值得注意的是,在μC/OS-II中,信号量一旦建立就不能删除了,因此也就不可能将一个已分配的任务控制块再放回到空闲ECB链表中。如果有任务正在等待某个信号量,或者某任务的运行依赖于某信号量的出现时,删除该任务是很危险的。
程序清单L6.9建立一个信号量
OS_EVENT*OSSemCreate(INT16Ucnt)
{
OS_EVENT*pevent;
OS_ENTER_CRITICAL();
pevent=OSEventFreeList;(1)
if(OSEventFreeList!=(OS_EVENT*)0){(2)
OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if(pevent!=(OS_EVENT*)0){(3)
pevent->OSEventType=OS_EVENT_TYPE_SEM;(4)
pevent->OSEventCnt=cnt;(5)
OSEventWaitListInit(pevent);(6)
}
return(pevent);(7)
}
6.6.2 等待一个信号量,OSSemPend()
程序清单L6.10是OSSemPend()函数的源代码。它首先检查指针pevent所指的任务控制块是否是由OSSemCreate()建立的[L6.10(1)]。如果信号量当前是可用的(信号量的计数值大于0)[L6.10(2)],将信号量的计数值减1[L6.10(3)],然后函数将“无错”错误代码返回给它的调用函数。显然,如果正在等待信号量,这时的输出
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
