目录1.同步与互斥的概念同步互斥同步互斥理解图2.同步的例子_有缺陷代码同步的缺陷3.互斥的例子_有缺陷4.FreeRTOS的解决方案FreeRTOS的解决方案多种解决方案队列事件组信号量互斥量任务通知1.同步与互斥的概念一个场景两个人同时想上厕所然后有一个抢占先机去了厕所另外一个人在外面同步我正在用厕所你等会互斥我正在用厕所你不能进来同步与互斥经常放在一起讲是因为它们之的关系很大“互斥”操作可以使用“同步”来实现。我“等”你用完厕所我再用厕所。这就是用“同步”来实现“互斥”同步互斥理解图任务A先触发了串口的条件任务B也想用串口但是已经没有位置只能进入阻塞状态等待任务A用完串口后唤醒任务B然后任务B使用串口同一时间只能有一个人使用的资源被称为临界资源。比如任务A、B都要使用串口来打印串口就是临界资源。如果A、B同时使用串口那么打印出来的信息就是A、B混杂无法分辨。所以使用串口时应该是这样A用完B再用B用完A再用2.同步的例子_有缺陷程序在06_create_task_use_params的基础上修改出12_task_sync_exclusion使用的是全局变量作为等待标志位但是这样的话CPU的运行效率会降低所以在使用同步的时候需要考虑怎样提高处理器的性能代码任务1和任务2都是有调度的任务1和任务2会交替运行的但是在任务1还没有完成计算的时候任务2只能一直的死循环只要任务1完成了计算任务2才能执行打印的任务这样的话CPU的效率会降低假设任务1加入了任务2的运行时间为2.5ms只有任务1的话把任务2去除了运行时间会变成1.2ms为了提高CPU的性能让那些等待的任务不参与CPU的调度进入阻塞状态同步的缺陷会使得CPU效率降低3.互斥的例子_有缺陷程序06_create_task_use_params的互斥缺陷在上述程序中OLED屏幕就是临界资源同一时间只能有一个任务访问因为OLED是I2C通信的必须要使用互斥保护这个I2C通信如果通信不完整的话OLED是无法显示的在这个代码中使用全局变量来保护I2C是有缺陷的全局变量的缺陷假设任务A进入了if判断了刚进去到112行时还没有把g_LCDCanUse置0就被切换为任务B了任务B置0使用了OLED使用到一半的时候有切换为任务A因为在上一次的调度中任务A已经进入了if判断即使g_LCDCanUse置0任务A一样可以用OLED那么就会出现任务A和任务一起使用OLED的情况这种使用全局变量保护临界资源但是被两个任务同时使用的概率是很低的就是在刚进入临界资源时来了一个Tick中断的概率是非常非常低的所以大部分情况下全局变量保护临界资源的方法是可行的但有缺陷就是一个程序运行成千上万次时有可能发送一个临界资源被两个任务同时使用为了减小这种情况发生的概率要在加入一个步骤在加入临界资源的判断时来一个初始值为1局部变量然后使用--后缀语法让这个变量为0只有这个变量为0时才能使用临界资源把第 4 行的代码使用汇编指令表示如下不要看第4行只有一个代码要是换成汇编指令是有3个指令的所以即使在刚进入临界资源的判断时来了一个Tick中断刚被切换的任务也来不及完成这三个指令但是执行的指令也是会被任务调度保存的所以上述的全局变量的缺陷还是会存在的只是概率减小了要想解决全局变量的缺陷先关中断判断完这个变量之后再去开中断使用FreeRTOS提供的关闭全局中断的底层接口函数disable_irq();完成任务之后再开中断使用开启全局中断的底层接口函数enable_irq();例子1例子2但是这个方法还有不足够之处当还有一个函数A调用LCD_PrintString然后有两个任务都是通过使用函数A内有死循环来使用OLED屏幕的那么有一个任务A成功了那么任务B加入失败就一直返回-1直到任务A使用了才会进去使用OLED那么不就回到了同步的缺陷了嘛降低了CPU的效率那么解决方法就是在任务B返回-1时让他进入阻塞状态不参与CPU的调度全局变量的互斥保护的缺陷会在使用临界资源时发生Tick中断产生两个任务使用一个临界资源的现象全局变量的互斥保护加上开启中断和关闭中断的缺陷变为了同步的缺陷4.FreeRTOS的解决方案任务之间的通信时靠全局变量来通信的但是会出现上述的缺陷还要一种可能当任务A刚写好了一个全局变量任务B就读走了这样就会发生全局变量不一样的现象FreeRTOS的解决方案保证了正确性保证了高效率阻塞和同步唤醒的机制多种解决方案队列队列可以理解一个传送带任务A和任务B是生产者任务C和任务D是消费者一个或多个工人都可以往这个传送带上放产品消费者就通过传送带拿产品事件组事件组就是事件的组合在里面有个整数每一位代表一种事件任务A和任务B是生产者任务C和任务D是消费者生产者做完某事后就将该事件置1表示这个事情做完了消费者为阻塞状态等待某一个事件或几个事件还能等待若干事件中的某一个事件信号量任务A和任务B是生产者任务C和任务D是消费者生产者生产一个产品就加1消费者消费一个产品就减1互斥量将信号量的计数值设置为单纯的0和1就变成了互斥量使用互斥量来保存某些临界资源任务通知多对一的关系在左边有很多个任务通过任务通知的办法来通知某一个任务可以是数值也可以是事件