信号量的作用
信号量主要用作线程间的同步及互斥,信号量的获取不能在ISR中调用,会导致中断挂起,系统不能有效的进行线程切换及运行。信号量分为动态创建信号量和静态创建信号量,当创建信号量时系统会初始化IPC以及与semaphone相关的部分。在创建信号量指定的参数过程中,flag参数定义FIFO时,信号量采取先入先出的方式,定义为IPRO时,信号量采取优先级的方式,优先级高的线程将先获得等待的信号量。
静态创建信号量
rt_err_t rt_sem_init (rt_sem_t sem, const char* name, rt_uint32_t value, rt_uint8_t flag);/在内存编译时间就编译出来,放在数据段或ZI段上,初始化成功将返回RT_OK/
动态创建信号量
rt_sem_t rt_sem_create (const char* name, rt_uint32_t value, rt_uint8_t flag);/初始化成功将返回创建的信号量控制块指针,否则返回RT_NULL/
删除信号量
rt_err_t rt_sem_delete (rt_sem_t sem);/调用这个函数时,系统将去删除信号量,当有线程任务在等待该信号量时,系统将优先调用等待的线程,赋给等待线程的返回值为-RT_ERROR,注意sem参数必须是create创建的信号量/
脱离信号量
rt_err_t rt_sem_detach (rt_sem_t sem);/调用这个函数用于让信号从内核对象管理器中移除掉,当有信号量正在等待获取时,系统首先去让等待的函数返回-RT_ERROR,注意sem参数是init创建信号量的信号量句柄/
获取信号量
rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time);/等待获取信号量,time定义了获取信号量的等待时间,未解决问题,当定义time时间为0时,线程会直接返回,是退出线程吗?/
rt_err_t rt_sem_trytake(rt_sem_t sem);/无等待获取信号量,和rt_sem_take(sem,0)效果相同/
释放信号量
rt_err_t rt_sem_release(rt_sem_t sem);/执行代码内容去释放信号量/
下列是动态创建信号量并让LED灯闪烁的示例代码
#define LED0 82
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 20
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static rt_sem_t semaphone1= RT_NULL;
static rt_sem_t semaphone2= RT_NULL;
static void entry_critical1()
{
while(1)
{
rt_sem_take(semaphone2,RT_WAITING_FOREVER);
{
rt_pin_write(LED0,1);
rt_thread_mdelay(500);
rt_sem_release(semaphone1);
}
}
}
static void entry_critical2()
{
while(1)
{
rt_sem_take(semaphone1,RT_WAITING_FOREVER);
{
rt_pin_write(LED0,0);
rt_thread_mdelay(500);
}
rt_sem_release(semaphone2);
}
}
int main(void)
{
rt_int32_t sem1 = 0;
rt_int32_t sem2 = 1;
rt_pin_mode(LED0, PIN_MODE_OUTPUT);
dma_check_task_init();
user_uart_init(USER_UART_2);
user_node_init();
semaphone1 = rt_sem_create("sem1",sem1,RT_IPC_FLAG_FIFO);//创建动态信号量
semaphone2 = rt_sem_create("sem2",sem2,RT_IPC_FLAG_FIFO);//创建动态信号量
tid1 = rt_thread_create("t1",entry_critical1, RT_NULL,THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
else
return -1;
tid2 = rt_thread_create("t2",entry_critical2,RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY,THREAD_TIMESLICE-2);
if(tid1 != RT_NULL)
rt_thread_startup(tid2);
else
return -1;
}