1. 信号量的理解 (1)uc/os-ii的信号量是由两个部分组成:一部分是16位的无符号整型信号量的计数值(0~65535);另一部分是等待该信号量的任务组成的等待任务表。(另外参考事件控制块ECB)
(2)信号量可以是2值的变量(称为二值信号量),使用OSMutextCreate创建, 也可以是计数式的, 使用OSSemCreate。根据信号量的值,内核跟踪那些等待信号量的任务。
(3)建立信号量的工作必须在任务级代码中或者多任务启动之前完成。
(4)任务要得到信号量的问题。
想得到信号量的任务,必须执行等待操作(pend)。如果信号量有效(非0),则信号量减1,任务得以继续运行。如果信号量无效,则等待信号量的任务就被列入等待信号量的任务表中。多少内核允许定义等待超时,当等待时间超过了设定值,该信号量还是无效,则等待该信号量的任务进入就绪态,准备运行,并返回出错代码(等待超时错误)。
(5)任务对信号量的释放问题。
任务执行发信号(post)操作来释放信号量。如果没有任务等待信号量,那么信号量的值仅是简单的加1(则信号量大于0,有效);如果有任务等待该信号量,那么就会有另一个任务进入就绪态,信号量的值就不加1。
之后,这个释放的信号量给那个等待中的任务,要看内核如何调度的。收到信号量的任务可能是如下两者之一:
◆等待任务中,优先级最高的;(uc/os-ii仅支持这种方式)。
◆最早开始等待信号量的任务(如果是按先进先出FIFO原则)。
2. 信号量的有效与无效问题 信号量有效:信号量的计算器非0(.OSEventCnt!=0)。信号量有效表示任务对资源可用。
信号量无效:信号量的计算器为0。信号量无效表示任务对目前资源不可用,需要等待其他另一个任务(或者中断服务子程序)发出该信号量(OSSemPost)。
3. 信号量的值(.OSEventCnt)大小表示什么? 二值信号量Mutext,表示任务可以独占共享资源。
计数式信号量Semaphore,用于某资源可同时为N个任务所用。
4. 信号量是如何实现任务之间的通信的? (1)信号量的建立必须是在任务级中建立,
(2)信号量类型为OS_EVENT ,信号量值可以为1和0(Mutex二值信号量),0~65535(计数式信号量Semaphore)的值,不同的值代表不同的意义。
(3)信号量(这里仅说互斥)就两个操作,一个请求,一个释放。
(4)一个任务请求信号量时:如果被其它任务占用,则该任务等待,同时导致任务切换;
如果没有被其它任务占用,则获得,继续执行。
(5)释放信号量时,如果其它高优先级任务正在请求并等待该信号量,则导致任务切换。
(6)OSTimeDly之类,并不导致信号量的释放。只有获取信号量的那个任务调用释放功能时,信号量才会释放。
(7)OSSemAccept(信号量)起查询信号量作用,返回信号量的值。
(8)OSSemPend(sem,timeout,&err),timeout代表等待timeout个信号量后还没得到信号量,恢复运行状态,如果timeout=0,表示无限等待信号量。
OSSemPend(sem,0,&err);
将暂停当前任务,等待信号量的到来。
5. 信号量有关的三个重要函数分析
◆OSSemCreate() 创建一个信号量(注:由任务或启动代码操作) 创建工作必须在任务级代码中或者多任务启动之前完成。功能只要是先获取一个事件控制块ECB,写入一些参数。其中调用了OS_EeventWaitListInt()函数,对事件控制块的等待任务列表进行初始化。完成初始化工作后,返回一个该信号量的句柄(Handle)。
◆OSSemPend( )或者OSMutextPend( ) 等待/请求一个信号量 (注:只能由任务操作) 本函数应用于任务试图获得共享资源的使用权、任务需要与其他任务或中断同步及任务需要等待特定事件发生的场合。
如果任务Task_A调用OSSemPend(),且信号量的值有效(非0),那么OSSemPend()递减信号量计数器(.OSEventCnt),并返回该值。换句话说,Task_A获取到共享资源的使用权了,之后就执行该资源。
如果如果任务Task_A调用OSSemPend(),信号量无效(为0),那么OSSemPend()调用 OS_EventTaskWait()函数,把Task_A放入等待列表中。(等待到什么时候呢?要看OSSemPost()(或者等待超时情况),由它 释放信号量并检查任务执行权,见下资料)
◆OSSemPost()或者OSMutextPost( ) 发出/释放一个信号量 (注:由任务或中断操作) 本函数其中调用OS_EventTaskRdy()函数,把优先级最高的任务Task_A(在这假如是Task_A,另外假设当前调用OSSemPost()的任务是Task_B)从等待任务列表中去除,并使它进入就绪态。然后调用OSSched()进行任务调度。如果Task_A是当前就绪态中优先级最高的任务,则内核执行Task_A;否则,OSSched()直接返回,Task_B继续执行.
6 互斥型信号量
1.互斥型信号量(mutex) 互斥型信号量具备uc/os-ii信号量的所有机制,但还具有其他一些特性。
任务可利用互斥型信号量来实现对共享资源的独占处理。
Mutex是二值信号量,1表示资源是可以使用的。
2.关于优先级反转 下面概述优先级反转原理:
假设有三个任务,分别命名为A,B,C;A的优先级最高,C的优先级最低。任务A和任务B处于挂起状态(请注意这条件),等待某一事件的发生,任务C正在运行。当任务C等待到共享资源(命名为S1)并使用后,如果任务A等待得事件到来之后,由于A的优先级最高,所以就会剥夺任务C的CPU使用权。运行过程中,任务A也要使用资源S1,但S1的信号量还被任务C占用着,所有任务A只能进入挂起状态,等待任务C对S1的信号量的释放。此时任务C得以继续运行。
同理,任务B的事件到来后,会剥夺任务C的CPU使用权。任务B把事情搞定以后,把CPU使用权归还给任务B(呵呵,优先级低就是给人欺负啊,所以做人还真的要争口气!)。任务B又得以继续运行,任务B认真处理完毕资源S1后,终于可以释放S1的信号量。而处于等待该信号量的任务A马上得到信号量并开始处理共享资源S1。
综述上面情况,任务C和任务A的优先级发生了反转。
而互斥型信号量就是具有解决优先级反转问题的特性。
3.uc/os-ii的互斥型信号量由三个部分组成: ◆一个标志,指示mutex是否可以使用(0或1)
◆一个优先级,准备一旦高优先级的任务需要这个mutex,赋予给占有mutex的任务。
◆一个等待该mutex的任务列表。
【┈┈【C|ucos-ii信号量总结】