信号量相当于裸机中的标志
信号量可以由不同的线程释放,互斥量必须由相同的线程释放。
信号量:实现线程间的通信,同步或临界资源的互斥访问。多线程系统中,线程间需要同步或互斥实现临界资源保护。二值信号量:用于线程间、线程与中断间的同步。其他线程获取,信号量为0,释放信号量为1。二值信号量最大计数值为1。也就是信号量的个数最大为1。是计数型信号量的特殊情况(计数最大值为1)。
注意 信号量的获取是一种阻塞式的 就是没有获取到信号量 就不会向下执行,这个线程被信号量挂起
看下面代码,如果别的线程没有释放信号量,虽然us_flag等于RT_EOK 但不会往下执行
相当于rt_sem_take ()获取到一次信号量 程序才会向下执行一次
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
while(1)
{
us_flag=rt_sem_take(syn_sem, RT_WAITING_FOREVER);//这里被阻塞了 这个线程被信号量挂起
if(us_flag==RT_EOK) //都不会往下执行
{
tt++; //不会执行++
rt_thread_mdelay(400);
rt_mq_send( msg_mq, // 写入(发送)队列的ID(句柄)
&filtered_val, // 写入(发送)的数据所对应地址
sizeof(filtered_val)// 数据的长度
);
if(tt>=20){ us_flag=RT_EBUSY;tt=0;}
}
else
rt_thread_mdelay(400);
}
正确写法如下: 因为 rt_sem_take(syn_sem, RT_WAITING_FOREVER); 会死等信号量释放 线程会被挂起
/********************************************************************************************************************************
线程入口
*******************************************************************************************************************************/
static void Send_P01_thread_entry(void *parameter)
{
while(1)
{
//rt_thread_mdelay(300);
rt_sem_take(syn_sem, RT_WAITING_FOREVER);
rt_mq_send( msg_mq, // 写入(发送)队列的ID(句柄)
&filtered_val, // 写入(发送)的数据所对应地址
sizeof(filtered_val)// 数据的长度
);
AT32_LEDn_Toggle(LED1);
}
}
释放信号量函数会将调用恢复阻塞态线程的函数,同时会调用调度函数执行线程调度。
二值信号量:若还有因读信号量而被阻态的线程,那只能等被阻态的所有线程都就绪后,再次释放才能真正释放。比如,我二值信号量我设定初始值为0,然后有个线程获取它,那个线程就会挂起,然后等中断里释放这个信号量时,“释放”的操作是这样的:若有因这个信号量而阻塞的线程则先恢复这个线程并执行一次调度——但此时是信号量这个值和线程恢复二选一的,若存在阻塞的线程,那么释放信号量时其值就不累加了。所以不是说释放二值信号量它的值就会++!不是说释放二值信号量它的值就会++!不是说二值信号量释放它的值就会++! 而是在没有阻塞情况下,是++的,在有阻塞线程下,不++的,而是先恢复线程的!
二值信号量特性:(1)前提是要先创建信号量。(2)获取和释放要成对出现。(3)读取未被释放好的二值信号量的所有线程都会被移除就绪表而被挂起,同时这些线程又会按照FIFO先进先出或者优先级的顺序被挂到这个二值信号量控制块下的成员suspend链表下。调用释放函数时从suapend的next恢复掉一个线程——而不是一下子恢复掉所有线程,一个一个来!(4)二值信号量的意义:这样子就完成了第一个线程中获取信号量函数到释放信号量函数之间的代码运行完了,才能再去运行下个获取同样这个信号量的线程中获取和释放的这部分代码。以此类推。假如把获取信号量和释放信号量这个区间当成代码区间。理想的执行顺序:先运行存在这种区间的最高优先级线程的区间1这段代码,再运行次高优先级线程的区间2,在运行第3高优先级线程的区间3,……,直到最后用到这个二值信号量的线程中的区间n。实际上的运行顺序还得根据延时时间动态判断。
————————————————
版权声明:本文为CSDN博主「huibin.yun」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yhb1206/article/details/102595708
网友评论