浅析μC/OS-ⅡAPI的设计思想及实现机制
μC/OS-II提供了5个对信号量进行操作的函数。它们是:OSSemCreate(),OSSemPend(),OSSemPost(),OSSemAccept()和OSSemQuery()函数。图 F6.5说明了任务、中断服务子程序和信号量之间的关系。图中用钥匙或者旗帜的符号来表示信号量:如果信号量用于对共享资源的访问,那么信号量就用钥匙符号。符号旁边的数字N代表可用资源数。对于二值信号量,该值就是1;如果信号量用于表示某事件的发生,那么就用旗帜符号。这时的数字N代表事件已经发生的次数。从图 F6.5中可以看出OSSemPost()函数可以由任务或者中断服务子程序调用,而OSSemPend()和OSSemQuery()函数只能有任务程序调用。
3.1建立一个信号量, OSSemCreate()
OS_EVENT *OSSemCreate (INT16U cnt)
函数参数传递的是要创建的信号量的初始值,在函数内部对任务控制块进行初始化。OSSemCreate()返回给调用函数一个指向任务控制块的指针。以后对信号量的所有操作,如OSSemPend(), OSSemPost(), OSSemAccept()和OSSemQuery()都是通过该指针完成的。因此,这个指针实际上就是该信号量的句柄。如果系统中没有可用的任务控制块,OSSemCreate()将返回一个NULL指针。
值得注意的是,在μC/OS-II中,信号量一旦建立就不能删除了,因此也就不可能将一个已分配的任务控制块再放回到空闲ECB链表中。如果有任务正在等待某个信号量,或者某任务的运行依赖于某信号量的出现时,删除该任务是很危险的。
3.2等待一个信号量, OSSemPend()
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
它首先检查指针pevent所指的任务控制块是否是由OSSemCreate()建立的。如果信号量当前是可用的(信号量的计数值大于0),将信号量的计数值减1,然后函数将“无错”错误代码返回给它的调用函数。显然,如果正在等待信号量,这时的输出正是我们所希望的,也是运行OSSemPend()函数最快的路径。
3.3发送一个信号量, OSSemPost()
INT8U OSSemPost (OS_EVENT *pevent)
它首先检查参数指针pevent指向的任务控制块是否是OSSemCreate()函数建立的,接着检查是否有任务在等待该信号量。如果该任务控制块中的.OSEventGrp域不是0,说明有任务正在等待该信号量。这时,就要调用函数OSEventTaskRdy(),使一个任务进入就绪状态,把其中的最高优先级任务从等待任务列表中删除并使它进入就绪状态。然后,调用OSSched()任务调度函数检查该任务是否是系统中的最高优先级的就绪任务。如果是,这时就要进行任务切换[当OSSemPost()函数是在任务中调用的],准备执行该就绪任务。如果不是,OSSched()直接返回,调用OSSemPost()的任务得以继续执行。如果这时没有任务在等待该信号量,该信号量的计数值就简单地加1。
上面是由任务调用OSSemPost()时的情况。当中断服务子程序调用该函数时,不会发生上面的任务切换。如果需要,任务切换要等到中断嵌套的最外层中断服务子程序调用OSIntExit()函数后才能进行。
3.4无等待地请求一个信号量, OSSemAccept()
INT16U OSSemAccept (OS_EVENT *pevent)
当一个任务请求一个信号量时,如果该信号量暂时无效,也可以让该任务简单地返回,而不是进入睡眠等待状态。这种情况下的操作是由OSSemAccept()函数完成的。该函数在最开始也是检查参数指针pevent指向的事件控制块是否是由OSSemCreate()函数建立的,接着从该信号量的事件控制块中取出当前计数值,并检查该信号量是否有效(计数值是否为非0值)。如果有效,则将信号量的计数值减1,然后将信号量的原有计数值返回给调用函数。调用函数需要对该返回值进行检查。如果该值是0,说明该信号量无效。如果该值大于0,说明该信号量有效,同时该值也暗示着该信号量当前可用的资源数。应该注意的是,这些可用资源中,已经被该调用函数自身占用了一个(该计数值已经被减1)。中断服务子程序要请求信号量时,只能用OSSemAccept()而不能用OSSemPend(),因为中断服务子程序是不允许等待的。
3.5查询一个信号量的当前状态, OSSemQuery()
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
在应用程序中,用户随时可以调用函数OSSemQuery()来查询一个信号量的当前状态。该函数有两个参数:一个是指向信号量对应事件控制块的指针pevent。该指针是在生产信号量时,由OSSemCreate()函数返回的;另一个是指向用于记录信号量信息的数据结构OS_SEM_DATA(见uCOS_II.H)的指针pdata。因此,调用该函数前,用户必须先定义该结构变量,用于存储信号量的有关信息。在这里,之所以使用一个新的数据结构的原因在于
- 3DES算法的FPGA高速实现(06-21)
- 基于DSP的Max-Log-MAP算法实现与优化(05-27)
- DSP中DMA操作的无阻塞请求实现(06-18)
- 二维DCT编码的DSP实现与优化(09-08)
- 基于DSP处理器上并行实现ATR算法(01-29)
- 基于DSP的H.324终端设计(05-27)