一:信号量的理解:
(1)信号量可以分为两种:一种是二值信号量(0和1),一种是N值信号量(计数式信号量)。
二值信号量的意思是可以有多少任务同时享用这个信号量。比如二值信号,就是只有1个任务可以使用。当有一个任务使用该信号量的时候,那么其他需要使用该信号量的任务就必须等待,直到该任务释放该信号量。这种信号量可以看作一把钥匙。
对于N值信号量(计数式信号量),就是说可以同时有N-1个任务同时使用该信号量。对于二值信号量,N=1。
(2)建立信号量的工作必须在任务级代码中或者多任务启动之前完成。
二:任务如何得到信号量的问题:
想得到信号量的任务,必须执行等待操作(pend)。在信号量的建立的时候,我们首先确定了该信号量可以被共享的资源数(N),并将其赋值给pevent->OSEventCnt。如果信号量有效(非0),即pevent->OSEventCnt>0,则信号量减1,任务得以继续运行。如果信号量无效,即pevent->OSEventCnt==0,则等待信号量的任务就被列入等待信号量的任务表中。许多内核允许定义等待超时,当等待时间超过了设定值,该信号量还是无效,则等待该信号量的任务进入就绪态,准备运行,并返回出错代码(等待超时错误)。
三:任务对信号量的释放问题:
任务执行发信号(post)操作来释放信号量。如果没有任务等待信号量,那么信号量的值仅是简单的加1(则信号量大于0,有效);如果有任务等待该信号量,那么就会有另一个任务进入就绪态,信号量的值就不加1。
之后,这个释放的信号量给那个等待中的任务,要看内核如何调度的。收到信号量的任务可能是如下两者之一:
◆等待任务中,优先级最高的;(uc/os-ii仅支持这种方式)。
◆最早开始等待信号量的任务(如果是按先进先出FIFO原则)。
四:信号量的有效与无效的问题:
信号量有效:信号量的计算器非0(.OSEventCnt!=0)。信号量有效表示任务对资源可用。
信号量无效:信号量的计算器为0。信号量无效表示任务对目前资源不可用,需要等待其他另一个任务(或者中断服务子程序)发出该信号量(OSSemPost)。
五:关于信号量的三个重要函数:
◆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继续执行。