信号量的功能其实很简单,就是记录某个资源还剩余多少的数量
一个线程运行的时候,如果需要某个资源,就会来询问这个资源还有多少,这个信号量就是记录资源的数量
当线程使用这个资源的时候,就会获取这个信号量,会让这个信号量--,
当线程使用完之后,不再需要资源了,就要释放信号量,让信号量++。
1、获取信号量
获取信号量:
有信号量:成功
没有信号量:等待?
不等待:返回失败
等待:
将自己从readylist移除
将自己挂载在信号量的链表中
2、释放信号量
信号量++
如果信号量链表上有线程,唤醒这些线程
信号量结构体:
struct rt_semaphore
{
struct rt_ipc_object parent; /**< inherit from ipc_object */
rt_uint16_t value; /**< value of semaphore. */
rt_uint16_t reserved; /**< reserved field */
};
重要的就是value,表示信号量的数量。
分析代码:
1、创建信号量:
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag)
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
2、删除信号量:
rt_err_t rt_sem_detach(rt_sem_t sem)
rt_err_t rt_sem_delete(rt_sem_t sem)
3、获取信号量:
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t timeout)
获取信号量,如果信号量还有,直接获取就可以
if (sem->value > 0)
{
sem->value --; /* semaphore is available */
rt_hw_interrupt_enable(level); /* enable interrupt */
}
没有信号量,且不愿意等待,返回错误
if (timeout == 0)
{
rt_hw_interrupt_enable(level);return -RT_ETIMEOUT;
}
没有信号量,愿意等待:
将自己从readylist链表里面移除,挂在信号量的链表里面,开启线程的定时器
_ipc_list_suspend(&(sem->parent.suspend_thread),
thread,
sem->parent.parent.flag);
/* has waiting time, start thread timer */
if (timeout > 0)
{
RT_DEBUG_LOG(RT_DEBUG_IPC, ("set thread:%s to timer list\n",thread->name));/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),RT_TIMER_CTRL_SET_TIME,&timeout);
rt_timer_start(&(thread->thread_timer));
}
超时后,返回超时。
4、释放信号量
rt_err_t rt_sem_release(rt_sem_t sem)
释放信号量,不止是将信号量++,中间还有一些其他的操作:
查看信号量的链表里面有没有等待信号量挂起的线程,唤醒这些等待的线程。
if (!rt_list_isempty(&sem->parent.suspend_thread))
{
_ipc_list_resume(&(sem->parent.suspend_thread)); /* resume the suspended thread */
need_schedule = RT_TRUE;
}
之后再释放信号量,信号量++。