开启辅助访问 切换到窄版

打印 上一主题 下一主题

UCOSIII信号量和互斥信号量

[复制链接]
楼主
跳转到指定楼层
| 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在UCOSIII中在某一时刻可能会有多个任务来访问共享资源,信号量最早来控制任务访问共享资源,信号量现在也被用来实现任务间的同步以及任务和中断处理函数ISR的同步。在例如UCOSIII这个可剥夺的内核中,当任务独占信号量来使用共享资源时,就会出现低优先级任务先于高优先级任务运行的现象,即这种现象是优先级反转。优先级反转这个现象不应该在UCOSIII中出现,因为它违反了UCOSIII可剥夺的特性,所以为了解决优先级反转这个问题,UCOSIII引入了互斥信号量。。。。。。


本文讲解一下UCOSIII信号量和互斥信号量。


信号量
信号量相当于一种上锁机制,任务的代码必须要获得相应的信号量钥匙后才能执行,只要获得信号量,就意味着该任务具有进入被锁部分代码的权限,一旦执行到被锁代码段,任务就一直处于等待状态,知道对应被锁部分代码的钥匙被再次释放再执行。
信号量有两种类型:二进制信号量和计数型信号量,其中二进制信号量只能取0,1两个值,就像逻辑中的是与非,而计数型信号量不止可以取两个值,在共享资源中,只有任务才能使用信号量,在中断服务函数不能使用信号量,避免出现阻塞。


二进制信号量
某个资源对应的信号量为1时,就可以使用这个资源,相反,如果对应的资源的信号量为0,那么等待该信号量的任务就会被放进等到信号量的任务表中,在等待信号量的时候也可以设置超时时间,如果等待时间超过设置的超时时间,那么就意味着任务没有等待到信号量,此任务就会进入就绪态,任务以发信号的方式来操作信号量。若信号量为二进制信号量时,一次只能一个任务使用共享资源。

计数型信号量
在同时有多个任务要访问共享资源时,二进制信号量就不能使用了,我们转而使用计数型信号量,例如一个信号量初始化值为10,则表示只有前10个请求该信号量的任务可以使用该共享资源。之后的新任务需要等待前10个任务释放掉该信号量。每次只要有任务请求该信号量时,信号量值就会减1,直至0. 反之有任务释放掉该信号量后,信号量的值就会加1.

这里,列举了信号量的API函数,在之后的实验里都会使用到:
OSSemCreate()   :创建一个信号量
OSSemDel() :删除一个信号量
OSSemPend() :等待一个信号量
OSSemPendAbort(): 取消等待
OSSemPost():释放一个信号量
OSSemSet() :强制设置一个信号量值(不建议)


要使用信号量,就必须在之前创建一个信号量,在UCOSIII中使用函数OSSemCreate()来创建信号量,函数原型如下:

参数:p_sem:指向信号量的控制块,首先在调用此函数之前先定义一个全局信号量,则p_sem存放的是信号量的指针。OS_SEM SEM.
p_name:信号量的名字
cnt: 设置信号量的初始值,如果该值设置为1,则表示此信号量使用的是二进制信号量,若此值大于1,则使用的是计数型信号量。
p_err: 保存调用此函数后返回的错误码


请求信号量
当一个任务需要独占式的访问某个特定的系统资源时,需要与其他任务或中断服务程序同步,或者需要等待某个事件的发生,应该调用函数OSSemPend(),原型如下:

参数:p_sem:指向一个信号量的指针。
timeout:指定等待信号量的超时时间(时钟节拍),若在指定时间内没有信号量则恢复任务执行,若此参数为0,则任务一直等待,直到等到信号量。
opt:选项:OS_OPT_PEND_BLOCKING:指定信号量无效时,任务挂起来等待信号量。
OS_OPT_PEND_NON_BLOCKING:信号量无效时,任务直接返回。
p_ts:指向一个时间戳
p_err:错误码。


发送信号量
任务获得信号量以后就可以直接访问共享资源了,在任务访问完共享资源后则必须释放信号量,释放信号量也叫发送信号量,使用函数OSSemPost()发送信号量。若没有任务在等待该信号量,则OSSemPost()只是简单将信号量加1,然后返回调用该函数的任务中继续运行。如果有一个或者多个任务在等待这个信号量,则优先级最高任务获得这个信号量。后做任务切换。
OSSemPost():

p_sem:指向一个信号量指针。
opt:选择信号量发送的方式:
OS_OPT_POST_1:仅向等待该信号量优先级最高的任务发送信号量。
OS_OPT_POST_ALL:向等待该信号量所有任务发送信号量。
OS_OPT_POST_NO_SCHED:禁止在本函数使用任务调度。

互斥信号量
为了避免优先级反转问题,UCOSIII支持一种特殊的二进制信号量:互斥信号量。

只有任务才能使用互斥信号量,且任务最多可对该互斥信号量嵌套使用250次。
这里,列举了互斥信号量的API函数
      OSMutexCreate():创建一个互斥信号量

      OSMutexDel():删除一个互斥信号量
OSMutexPend():等待一个互斥信号量
      OSMutexPendAbort():取消等待
OSMutexPost():释放互斥信号量

如果占用互斥信号量的任务比当前申请该互斥信号量的任务优先级低的话,OSMutexPend()函数会将占用互斥信号量的任务优先级暂时提升到当前申请任务的优先级,当最后释放掉互斥信号量时,再重新恢复之前的优先级。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表