要传输较大数据时,使用队列。
传输较小数值时,使用邮箱。
队列、邮箱用来传递数据。
如果只是用来传递资源的个数,可以使用信号量。
A车与B车只需要传递信号量(代表资源)。
信号量
获取信号量
- 如果value>0,value–,return OK;如果value0,timeout0,return -ETIMEOUT;如果value==0,timeout>0,从就绪链表移除(挂起),把自己记录在信号量的等待链表。
- 被唤醒:如果thread->err!=0,return thread->err;return EOK;
释放信号量
- value++;如果有等待信号量线程,唤醒线程。
创建信号量
/*** This function will create a semaphore from system resource** @param name the name of semaphore* @param value the initial value of semaphore* @param flag the flag of semaphore** @return the created semaphore, RT_NULL on error happen** @see rt_sem_init*/
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
信号量结构体
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 */
};struct rt_ipc_object
{struct rt_object parent; /**< inherit from rt_object */rt_list_t suspend_thread; /**< threads pended on this resource */
};
获取信号量
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
{register rt_base_t temp;struct rt_thread *thread;/* parameter check */RT_ASSERT(sem != RT_NULL);RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(sem->parent.parent)));/* disable interrupt */temp = rt_hw_interrupt_disable(); //关中断RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s take sem:%s, which value is: %d\n",rt_thread_self()->name,((struct rt_object *)sem)->name,sem->value));if (sem->value > 0) //如果有资源{/* semaphore is available */sem->value --;/* enable interrupt */rt_hw_interrupt_enable(temp);}else{/* no waiting, return with timeout */if (time == 0){rt_hw_interrupt_enable(temp);return -RT_ETIMEOUT;}else{/* current context checking */RT_DEBUG_IN_THREAD_CONTEXT;/* semaphore is unavailable, push to suspend list *//* get current thread */thread = rt_thread_self();/* reset thread error number */thread->error = RT_EOK;RT_DEBUG_LOG(RT_DEBUG_IPC, ("sem take: suspend thread - %s\n",thread->name));/* suspend thread */rt_ipc_list_suspend(&(sem->parent.suspend_thread),thread,sem->parent.parent.flag);/* has waiting time, start thread timer */if (time > 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,&time);rt_timer_start(&(thread->thread_timer));}/* enable interrupt */rt_hw_interrupt_enable(temp);/* do schedule */rt_schedule();if (thread->error != RT_EOK){return thread->error;}}}RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(sem->parent.parent)));return RT_EOK; //获取到了资源成功返回
}
RTM_EXPORT(rt_sem_take);
释放信号量
rt_err_t rt_sem_release(rt_sem_t sem)
{register rt_base_t temp;register rt_bool_t need_schedule;/* parameter check */RT_ASSERT(sem != RT_NULL);RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent)));need_schedule = RT_FALSE;/* disable interrupt */temp = rt_hw_interrupt_disable();RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s releases sem:%s, which value is: %d\n",rt_thread_self()->name,((struct rt_object *)sem)->name,sem->value));if (!rt_list_isempty(&sem->parent.suspend_thread)) //是否有等待线程{/* resume the suspended thread */rt_ipc_list_resume(&(sem->parent.suspend_thread));//唤醒++,接收--,所以没有对sem->value做任何操作。need_schedule = RT_TRUE;}elsesem->value ++; /* increase value *//* enable interrupt */rt_hw_interrupt_enable(temp);/* resume a thread, re-schedule */if (need_schedule == RT_TRUE)rt_schedule();return RT_EOK;
}
RTM_EXPORT(rt_sem_release);