举例子说明:同步的缺陷
首先创建两个任务:Task1和Task2;
让Task1执行一个比较耗时的计算,计算完成之后,通知Task2;
Task1:求和,sum++,累加10000000次,然后标志位置1
Task2:检测到标志位置1,打印sum值
为了可以在逻辑分析仪上更准确看到波形变化,这里将Task1任务执行完就删除掉
static int sum = 0;
static volatile int flagCalcEnd = 0;
void Task1Function(void * param)
{
/* 这里故意加上 volatile 防止系统优化掉 */
volatile int i = 0;
while(1)
{
for(i = 0; i < 10000000; i++)
sum++;
flagCalcEnd = 1;
vTaskDelete(NULL);
}
}
void Task2Function(void * param)
{
while(1)
{
if(flagCalcEnd)
printf("sum = %d\r\n",sum);
}
}
int main( void )
{
TaskHandle_t xHandleTask1;
/* 硬件初始化 */
prvSetupHardware();
xTaskCreate(Task1Function,"Task1",100,NULL,1,&xHandleTask1);
xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);
/* Start the scheduler. */
vTaskStartScheduler();
return 0;
}
分析一下:
1.由于两个任务的优先级都是1,不是0,因此空闲任务不会参与调度执行;
2.Tick中断一次1ms,1个Tick中断,发生一次任务调度事件,切换Task1与Task2;
3.逻辑分析仪抓取flagCalcEnd由初始化为0开始执行到置为1的整个过程耗时其实是Task1与Task2两个任务的耗时总和
4.甚至可以猜测Task1与Task2两个任务分别耗时应该是一致的
上图表明Task1与Task2两个任务耗时总和为6s
那么,如果只有Task1在运行呢?
我们可以修改程序,取消Task2的任务创建,如下:
int main( void )
{
TaskHandle_t xHandleTask1;
/* 硬件初始化 */
prvSetupHardware();
xTaskCreate(Task1Function,"Task1",100,NULL,1,&xHandleTask1);
//xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);
/* Start the scheduler. */
vTaskStartScheduler();
return 0;
}
下图图表明Task1只需要3S即可完成计算。
在上述例子中,Task1与Task2属于同步,因为Task2需要等待Task1输出标志位为1这个信号,才能去做自己的事情;
但是Task2在等待的过程中也依然占用了CPU的资源,这不符合RTOS的逻辑;
在这里这个例子的表现甚至没有优于裸机开发的效果。
这是同步的一个缺陷,那么FreeRTOS怎么能够忍受呢?它一定有相应的策略去解决这个问题。
继续往后看...