信号量管理

来源:互联网 发布:郑恺潮牌淘宝店 编辑:程序博客网 时间:2024/04/20 00:05

信号量管理

 

信号量是什么?

 

       信号量像一把钥匙,任务要运行下去就得先拿到这把钥匙,如果信号量被别的任务占用,那么申请信号量的任务就得挂起

 

为什么使用信号量?

      

       能够控制共享资源的使用权,能标志事件的发生,在多任务系统中普遍使用

 

信号量是怎么使用的?

 

       一般的说对信号量只能实施三种操做:初始化(initialize)或称为建立,等信号(wait)或挂起(pend),给信号或发信号(post)。信号量初始化时要给信号量附初值,等待信号量的任务列表应清空

 

1、建立一个信号量,OS_EVENT  *OSSemCreate (INT16U cnt)

 

如果信号量是表示一或多个事件发生的,那么该信号量的初始值通常附为0,如果信号量用于对共享资源的访问,那么该信号量的初始值应赋1

 

2、删除一个信号量,OSSemDel()

使用此函数时需要特别注意,多个任务可能试图操作已经删除的信号量。总之,在删除信号量之前,必须首先删除操作该信号量的所以任务

 

3、等待一个信号量,OSSemPend()

 

4、发出一个信号量,OSSemPost()

 

5、无等待的请求一个信号量,OSSemAccept()

当一个任务请求一个信号量时,如果该信号量暂时无效,亦可以让该任务简单的返回,而不是进入睡眠等待状态

 

6、查询一个信号量的当前状态,OSSemQuery()

      

互斥信号量

 

实现对共享资源的独占式处理。当高优先级的任务需要使用某共享资源,而该资源已被一个低优先级的任务占用时,就会发生优先级反转,为了降解优先级反转,内核可以将低优先级的任务的优先级提升到高于那个高优先级任务,直到低优先级任务使用完占用的共享资源

 

转:

 

信号量的理解

1uc/os-ii的信号量是由两个部分组成:一部分是16位的无符号整型信号量的计数值(0~65535);另一部分是等待该信号量的任务组成的等待任务表。(另外参考事件控制块ECB

2)信号量可以是2值的变量(称为二值信号量),也可以是计数式的。根据信号量的值,内核跟踪那些等待信号量的任务。

3)建立信号量的工作必须在任务级代码中或者多任务启动之前完成。

4)任务要得到信号量的问题。

想得到信号量的任务,必须执行等待操作(pend)。如果信号量有效(0),则信号量减1,任务得以继续运行。如果信号量无效,则等待信号量的任务就被列入等待信号量的任务表中。多少内核允许定义等待超时,当等待时间超过了设定值,该信号量还是无效,则等待该信号量的任务进入就绪态,准备运行,并返回出错代码(等待超时错误)

5)任务对信号量的释放问题。

任务执行发信号(post)操作来释放信号量。如果没有任务等待信号量,那么信号量的值仅是简单的加1(则信号量大于0,有效);如果有任务等待该信号量,那么就会有另一个任务进入就绪态,信号量的值就不加1

之后,这个释放的信号量给那个等待中的任务,要看内核如何调度的。收到信号量的任务可能是如下两者之一:

等待任务中,优先级最高的;(uc/os-ii仅支持这种方式)。

最早开始等待信号量的任务(如果是按先进先出FIFO原则)。

  

2 信号量的有效与无效问题

信号量有效:信号量的计算器非0.OSEventCnt=0)。信号量有效表示任务对资源可用。

信号量无效:信号量的计算器为0。信号量无效表示任务对目前资源不可用,需要等待其他另一个任务(或者中断服务子程序)发出该信号量(OSSemPost)。

3 信号量的值(.OSEventCnt)大小表示什么?

二值信号量,表示任务可以独占共享资源。

计数式信号量,用于某资源可同时为N个任务所用。

4 信号量是如何实现任务之间的通信的?

参见第1点的(4)(5)概述。

5 信号量有关的三个重要函数分析

OSSemCreate() 创建一个信号量   (注:由任务或启动代码操作)

创建工作必须在任务级代码中或者多任务启动之前完成。功能只要是先获取一个事件控制块ECB,写入一些参数。其中调用了OS_EeventWaitListInt()函数,对事件控制块的等待任务列表进行初始化。完成初始化工作后,返回一个该信号量的句柄(Handle)

  

OSSemPend() 等待一个信号量 (注:只能由任务操作)

本函数应用于任务试图获得共享资源的使用权、任务需要与其他任务或中断同步及任务需要等待特定事件发生的场合。

如果任务Task_A调用OSSemPend(),且信号量的值有效(0),那么OSSemPend()递减信号量计数器(.OSEventCnt),并返回该值。换句话说,Task_A获取到共享资源的使用权了,之后就执行该资源。

如果如果任务Task_A调用OSSemPend(),信号量无效(0),那么OSSemPend()调用OS_EventTaskWait()函数,把Task_A放入等待列表中。(等待到什么时候呢?要看OSSemPost()(或者等待超时情况),由它释放信号量并检查任务执行权,见下资料)

  

OSSemPost() 发出(释放)一个信号量 (注:由任务或中断操作)

本函数其中调用OS_EventTaskRdy()函数,把优先级最高的任务Task_A(在这假如是Task_A,另外假设当前调用OSSemPost()的任务是Task_B)从等待任务列表中去除,并使它进入就绪态。然后调用OSSched()进行任务调度。如果Task_A是当前就绪态中优先级最高的任务,则内核执行Task_A;否则,OSSched()直接返回,Task_B继续执行.

  互斥型信号量

1.互斥型信号量(mutex)

       互斥型信号量具备uc/os-ii信号量的所有机制,但还具有其他一些特性。

       任务可利用互斥型信号量来实现对共享资源的独占处理。

     Mutex是二值信号量,1表示资源是可以使用的。

  

2.关于优先级反转

    下面概述优先级反转原理:

       假设有三个任务,分别命名为A,B,CA的优先级最高,C的优先级最低。任务A和任务B处于挂起状态(请注意这条件),等待某一事件的发生,任务C正在运行。当任务C等待到共享资源(命名为S1)并使用后,如果任务A等待得事件到来之后,由于A的优先级最高,所以就会剥夺任务CCPU使用权。运行过程中,任务A也要使用资源S1,但S1的信号量还被任务C占用着,所有任务A只能进入挂起状态,等待任务CS1的信号量的释放。此时任务C得以继续运行。

       同理,任务B的事件到来后,会剥夺任务CCPU使用权。任务B把事情搞定以后,把CPU使用权归还给任务B(呵呵,优先级低就是给人欺负啊,所以做人还真的要争口气!)。任务B又得以继续运行,任务B认真处理完毕资源S1后,终于可以释放S1的信号量。而处于等待该信号量的任务A马上得到信号量并开始处理共享资源S1

    综述上面情况,任务C和任务A的优先级发生了反转。

       而互斥型信号量就是具有解决优先级反转问题的特性。

3uc/os-ii的互斥型信号量由三个部分组成:

       一个标志,指示mutex是否可以使用(01)

一个优先级,准备一旦高优先级的任务需要这个mutex,赋予给占有mutex的任务。

一个等待该mutex的任务列表。

本文出自 51CTO.COM技术博客

原创粉丝点击