## 信号量介绍 信号量(Semaphore)常用于协助一组互相竞争的任务来访问临界资源,在需要互斥的场合作为临界资源计数使用。 信号量对象具有一个内部计数器。它支持两种操作:申请(Pend)和释放(Post)。 - 任务执行Pend操作会等待指定的信号量,若其计数器值大于0,则计数器值直接减1,返回成功。否则任务阻塞,等待其他线程释放该信号量,等待的容忍时间可设定。 - 任务执行Post操作会释放指定的信号量,若没有其它任务等待该信号量,则直接将计数器加1,返回成功。否则如有任务阻塞,根据不同情况唤醒: 1. FIFO唤醒方式:SEM_MODE_FIFO,默认信号量唤醒方式,这种唤醒方式会唤醒最早阻塞于该信号量上的任务。 2. 优先级唤醒方式:SEM_MODE_PRIOR,核内信号量支持的唤醒方式,创建时指定,这种唤醒方式会唤醒阻塞于该信号量上的最高优先级的任务。 通常一个信号量的计数器值对应有效的资源数,表示剩下的可被占用的互斥资源数。其值的含义分两种情况: - 为0,表示没有积累下来的Post操作,且有可能有在此信号量上阻塞的任务。 - 为正值,表示当前有一个或多个可供Pend的信号量计数。 ## 运作机制 信号量是结合任务使用的,可以用作任务访问的临界资源的标识,通过信号量的Pend/Post 操作完成临界资源之间的互斥。 ### Pend操作原理 1. Pend操作后系统会判断信号量计数是否大于0,大于0则减1后返回操作成功,否则该任务进入阻塞态。进入阻塞态后系统将继续执行就绪任务队列中优先级最高的任务。 2. 任务进入阻塞态后,会等待信号量的释放,如果等待超时,则返回Pend操作失败。如果等待到信号量释放则返回操作成功。 ### Post操作原理 1. Post操作判断是否有任务阻塞于指定信号量,若没有,则对信号量计数加1直接返回,否则根据唤醒方式唤醒阻塞在该信号量的相应阻塞任务。若为FIFO方式,则唤醒最先阻塞的任务;若为优先级方式,则唤醒阻塞在此信号量的最高优先级任务。 ### 注意事项 - 目前,系统中运行的线程有硬中断和任务。对于信号量的P/V操作,在带有容忍时间的P操作过程中,如果P不到信号量,即会使自身阻塞于该信号量。硬中断不允许出现挂起和阻塞的状态,因此硬中断线程中不允许pend信号量。 - 等待互斥信号量的任务在等待超时后可能不会立刻得到运行。 - 不能在IDLE任务中等待信号量。 ### 具体使用流程 使用UniProton提供的信号量功能,要先创建信号量,然后申请信号量,临界资源使用完后,释放信号量,最后删除该信号量。