μC/OS-II的任务之间的通讯与同步
_EVENT*pevent)
{
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)
OS_EXIT_CRITICAL();
return(OS_ERR_EVENT_TYPE);
}
if(pevent->OSEventGrp){(2)
OSEventTaskRdy(pevent,(void*)0,OS_STAT_SEM);(3)
OS_EXIT_CRITICAL();
OSSched();(4)
return(OS_NO_ERR);
}else{
if(pevent->OSEventCnt65535){
pevent->OSEventCnt++;(5)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}else{
OS_EXIT_CRITICAL();
return(OS_SEM_OVF);
}
}
}
6.6.4 无等待地请求一个信号量,OSSemAccept()
当一个任务请求一个信号量时,如果该信号量暂时无效,也可以让该任务简单地返回,而不是进入睡眠等待状态。这种情况下的操作是由OSSemAccept()函数完成的,其源代码见程序清单L6.12。该函数在最开始也是检查参数指针pevent指向的事件控制块是否是由OSSemCreate()函数建立的[L6.12(1)],接着从该信号量的事件控制块中取出当前计数值[L6.12(2)],并检查该信号量是否有效(计数值是否为非0值)[L6.12(3)]。如果有效,则将信号量的计数值减1[L6.12(4)],然后将信号量的原有计数值返回给调用函数[L6.12(5)]。调用函数需要对该返回值进行检查。如果该值是0,说明该信号量无效。如果该值大于0,说明该信号量有效,同时该值也暗示着该信号量当前可用的资源数。应该注意的是,这些可用资源中,已经被该调用函数自身占用了一个(该计数值已经被减1)。中断服务子程序要请求信号量时,只能用OSSemAccept()而不能用OSSemPend(),因为中断服务子程序是不允许等待的。
程序清单L6.12无等待地请求一个信号量
INT16UOSSemAccept(OS_EVENT*pevent)
{
INT16Ucnt;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)
OS_EXIT_CRITICAL();
return(0);
}
cnt=pevent->OSEventCnt;(2)
if(cnt>0){(3)
pevent->OSEventCnt--;(4)
}
OS_EXIT_CRITICAL();
return(cnt);(5)
}
6.6.5 查询一个信号量的当前状态,OSSemQuery()
在应用程序中,用户随时可以调用函数OSSemQuery()[程序清单L6.13]来查询一个信号量的当前状态。该函数有两个参数:一个是指向信号量对应事件控制块的指针pevent。该指针是在生产信号量时,由OSSemCreate()函数返回的;另一个是指向用于记录信号量信息的数据结构OS_SEM_DATA(见uCOS_II.H)的指针pdata。因此,调用该函数前,用户必须先定义该结构变量,用于存储信号量的有关信息。在这里,之所以使用一个新的数据结构的原因在于,调用函数应该只关心那些和特定信号量有关的信息, 而不是象OS_EVENT数据结构包含的很全面的信息。
该数据结构只包含信号量计数值.OSCnt和等待任务列表.OSEventTbl[]、.OSEventGrp,而OS_EVENT中还包含了另外的两个域.OSEventType和.OSEventPtr。
和其它与信号量有关的函数一样,OSSemQuery()也是先检查pevent指向的事件控制块是否是OSSemCreate()产生的[L6.13(1)],然后将等待任务列表[L6.13(2)]和计数值[L6.13(3)]
从OS_EVENT结构拷贝到OS_SEM_DATA结构变量中去。
程序清单L6.13查询一个信号量的状态
INT8UOSSemQuery(OS_EVENT*pevent,OS_SEM_DATA*pdata)
{
INT8Ui;
INT8U*psrc;
INT8U*pdest;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)
OS_EXIT_CRITICAL();
return(OS_ERR_EVENT_TYPE);
}
pdata->OSEventGrp=pevent->OSEventGrp;(2)
psrc=pevent->OSEventTbl[0];
pdest=pdata->OSEventTbl[0];
for(i=0;i
*pdest++=*psrc++;
}
pdata->OSCnt=pevent->OSEventCnt;(3)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}
6.7 邮箱
邮箱是μC/OS-II中另一种通讯机制, 它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。该指针指向一个包含了特定“消息”的数据结构。为了在μC/OS-II中使用邮箱,必须将OS_CFG.H中的OS_MBOX_EN常数置为1。
使用邮箱之前,必须先建立该邮箱。该操作可以通过调用OSMboxCreate()函数来完成(见下节),并且要指定指针的初始值。一般情况下,这个初始值是NULL,但也可以初始化一个邮
箱,使其在最开始就包含一条消息。如果使用邮箱的目的是用来通知一个事件的发生(发送一
条消息),那么就要初始化该邮箱为NULL,因为在开始时,事件还没有发生。如果用户用邮箱
来共享某些资源,那么就要初始化该邮箱为一个非NULL的指针。在这种情况下,邮箱被当成一
个二值信号量使用。
μC/OS-II提供了5种对邮箱的操作:OSMboxCreate(),OSMboxPend(),OSMboxPost(),
OSMboxAccept()和 OSMboxQuery()函数。
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
