μC/OS-II的任务之间的通讯与同步
.OSTCBStat域中的OS_STAT_MBOX位,可以知道是否等待超时。如果该域被置1,说明任务等待已经超时[L6.15(7)]。这时,通过调用函数OSEventTo()可以将任务从邮箱的等待列表中删除[L6.15(8)]。因为此时邮箱中没有消息,所以返回的指针是NULL[L6.15(9)]。如果OS_STAT_MBOX位没有被置1,说明所等待的消息已经被发出。OSMboxPend()的调用函数得到指向消息的指针[L6.15(10)]。此后,OSMboxPend()函数通过将邮箱事件控制块的.OSEventPtr域置为NULL清空该邮箱,并且要将任务任务控制块中指向邮箱事件控制块的指针删除[L6.15(12)]。
6.7.3 发送一个消息到邮箱中,OSMboxPost()
程序清单L6.16是OSMboxPost()函数的源代码。检查了事件控制块是否是一个邮箱后[L6.16(1)],OSMboxPost()函数还要检查是否有任务在等待该邮箱中的消息[L6.16(2)]。如果事件控制块中的OSEventGrp域包含非零值,就暗示着有任务在等待该消息。这时,调用OSEventTaskRdy()将其中的最高优先级任务从等待列表中删除[见6.02节,使一个任务进入就绪状态,OSEventTaskRdy()][L6.16(3)],加入系统的就绪任务列表中,准备运行。然后,调用OSSched()函数[L6.16(4)],检查该任务是否是系统中最高优先级的就绪任务。如果是,执行任
务切换[仅当OSMboxPost()函数是由任务调用时],该任务得以执行。如果该任务不是最高优先
级的任务,OSSched()返回,OSMboxPost()的调用函数继续执行。如果没有任何任务等待该消息,
指向消息的指针就被保存到邮箱中[L6.16(6)](假设此时邮箱中的指针不是非NULL的[L6.16(5)])。这样,下一个调用OSMboxPend()函数的任务就可以立刻得到该消息了。
注意,如果OSMboxPost()函数是从中断服务子程序中调用的,那么,这时并不发生上下文的切换。如果需要,中断服务子程序引起的上下文切换只发生在中断嵌套的最外层中断服务子程序对OSIntExit()函数的调用时(见3.09节,μC/OS-II中的中断)。
程序清单L6.16向邮箱中发送一条消息
INT8UOSMboxPost(OS_EVENT*pevent,void*msg)
{
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_MBOX){(1)
OS_EXIT_CRITICAL();
return(OS_ERR_EVENT_TYPE);
}
if(pevent->OSEventGrp){(2)
OSEventTaskRdy(pevent,msg,OS_STAT_MBOX);(3)
OS_EXIT_CRITICAL();
OSSched();(4)
return(OS_NO_ERR);
}else{
if(pevent->OSEventPtr!=(void*)0){(5)
OS_EXIT_CRITICAL();
return(OS_MBOX_FULL);
}else{
pevent->OSEventPtr=msg;(6)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
}
}
6.7.4 无等待地从邮箱中得到一个消息,OSMboxAccept()
应用程序也可以以无等待的方式从邮箱中得到消息。这可以通过程序清单L6.17中的OSMboxAccept()函数来实现。OSMboxAccept()函数开始也是检查事件控制块是否是由OSMboxCreate()函数建立的 [L6.17(1)]。接着,它得到邮箱中的当前内容[L6.17(2)],并判断是否有消息是可用的[L6.17(3)]。如果邮箱中有消息,就把邮箱清空[L6.17(4)],而邮箱中原来指向消息的指针被返回给OSMboxAccept()的调用函数[L6.17(5)]。OSMboxAccept()函数的调用函数必须检查该返回值是否为NULL。如果该值是NULL,说明邮箱是空的,没有可用的消息。
如果该值是非NULL值,说明邮箱中有消息可用,而且该调用函数已经得到了该消息。中断服务子程序在试图得到一个消息时, 应该使用OSMboxAccept()函数, 而不能使用OSMboxPend()函数。
OSMboxAccept()函数的另一个用途是,用户可以用它来清空一个邮箱中现有的内容。
程序清单L6.17无等待地从邮箱中得到消息
void*OSMboxAccept(OS_EVENT*pevent)
{
void*msg;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_MBOX){(1)
OS_EXIT_CRITICAL();
return((void*)0);
}
msg=pevent->OSEventPtr;(2)
if(msg!=(void*)0){(3)
pevent->OSEventPtr=(void*)0;(4)
}
OS_EXIT_CRITICAL();
return(msg);(5)
}
6.7.5 查询一个邮箱的状态,OSMboxQuery()
OSMboxQuery()函数使应用程序可以随时查询一个邮箱的当前状态。程序清单L6.18是该函数的源代码。它需要两个参数:一个是指向邮箱的指针pevent。该指针是在建立该邮箱时,由OSMboxCreate()函数返回的;另一个是指向用来保存有关邮箱的信息的OS_MBOX_DATA(见
uCOS_II.H)数据结构的指针pdata。在调用OSMboxCreate()函数之前,必须先定义该结构变量,
用来保存有关邮箱的信息。之所以定义一个新的数据结构,是因为这里关心的只是和特定邮箱
有关的内容,而非整个OS_EVENT数据结构的内容。后
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
