1.信号量
使用信号量之前首先要对信号量有一个本质的认识
(1)信号量的含义:信号量是一类事件,使用信号量的最初目的是为了给共享资源
设立一个标志,该标志表示共享资源的占用情况,这样,当一个任务在访问共
享资源之前,就可以对这个标志进行查询,从而在了解资源被占用的情况之后
,再来决定自己的行为。
(2)UCOS-II的信号量里面有一个OSEventCnt,正确的认识这个,是使用信号量的关
键。
OSSemCreate(0) :这种情况下可以用任务的同步。
OSSemCreate(1) :这种情况类似于互斥信号量,有一个名字就是二值信号
量,可用于一个资源的使用
OSSemCreate(>1) :这种情况表示有>1个资源可以使用。
(3)OSEventCnt的初始数据代表可用的资源数,1就是一个可用资源,n就是n可用资
源。
(4)OSTimeTick 函数里面有一个需要注意的地方。
a如果事件中设置了0SxxxPend的延时的话,会进到下面函数的这个地方。
b如果设置的是一直等到的话,将通过OSXXXPost释放。
在延迟的时间里面没有就绪的话,任务OSTCBStatPend被设置成超时,并
清除相应的标志位。
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;
ptcb->OSTCBStatPend = OS_STAT_PEND_TO;
}
在延迟的时间里面任务收到信息,任务OSTCBStatPend被设置成OK
else
{
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
}
如果任务没有被挂起的话,任务将加入到就绪列表。
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
(5)下面分两种情况进行详细的讨论
A. OSSemCreate(0) 这种情况下用于信号的同步
- OSSemPen(xx, 0, xx) 设置为0的话,任务将被一直挂起直到收到OSSem
Post信号。
- OSSemPen(xx, >0, xx) 设置为>0的话,任务将被挂起相应的时间.
a)如果在规定的时间内收到信号,那么任务将通过OSSemPend将其从等待
列表删除,继续运行。
b)如果延时超时,那么将通过OSSemPend函数本身将其从事件等待列表删除
B. OSSemCreate(1) 这种情况下用于互斥信号量,但不能防止优先级翻转。
详细实现同上。
C. OSSemCreate(>1) 这种情况下用多个资源共享
详细实现同上。
OS_EventTaskRemove(OSTCBCur, pevent);
只是把任务从任务就绪列表里面移除,加入到事件等待列表
![1 1](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
2.信号量的创建
信号量的初始值的设置有三种作用已经在下面的图中有说明
![3 3](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
下面是一个信号量被初始化以后事件列表的情况
![4 4](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
3.请求信号量
![5 5](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![6 6](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![7 7](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
4.发送信号量
![8 8](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![9 9](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
信号量的使用还是很简单的
我现在主要将其用在两个方面
(1)用来触发一个事件的发生。
Semp = OSSemCreate(0); //创建一个信号量
static void AppTaskCom(void *p_arg) //这个任务用来申请一个信号量,在500毫秒里面可以
{ //得到信号量的话输出成功,否则失败。
INT8U err;
(void)p_arg;
while(1){
OSSemPend(Semp, 500, &err);
if(err == OS_ERR_NONE)
{
printf("SUCCESSrn");
}
else
{
printf("failedrn");
}
}
}
err = OSSemPost(Semp); //这个函数用来释放一个信号量
if (err == OS_ERR_NONE) //也就是触发上面的那个函数
{
printf("OSSemPostrn");
}
(2)用来独占一个资源,这个的使用要小心,防止优先级的反转,所以最好使用这两个资源的任务之间不要有别的优先级,有的话就容易发生优先级的反转情况,这种情况是不允许的。
OSSemPend(Semp, 500, &err);
//在这里添加需要使用的资源
OSSemPost(Semp);