1. 时间片概念
- 所谓时间片就是同一个优先级下可以有多个任务,每个任务轮流地享有CPU使用权,享有CPU的时间我们叫时间片。
- 在RTOS中,最小的时间单位为一个tick,即SysTick的中断周期,RT-Thread和μC/OS可以指定时间片的大小为多个tick,但是FreeRTOS不一样,时间片只能是一个tick。与其说FreeRTOS支持时间片,倒不如说它的时间片就是正常的任务调度。
2. 实验
2.1 实验过程
假设目前系统中有三个任务就绪(算上空闲任务就是4个),任务1和任务2的优先级都为2,任务3的优先级为3。
为了方便在逻辑分析仪中地分辨出任务1和任务2使用的时间片大小,任务1和任务2的主体编写成一个无限循环函数,不会阻塞,任务3的阻塞时间设置为1个tick。任务1和任务2的任务主体编写为一个无限循环,这就意味着,优先级低于2的任务就会被饿死,得不到执行,比如空闲任务。
要想任务3有机会执行,它的优先级就必须高于任务1和任务2的优先级,因此设置为3。
2.2 实验现象
3. FreeRTOS的时间片原理
之所以在同一个优先级下可以有多个任务,最终还是得益于taskRESET_READY_PRIORITY()和taskSELECT_HIGHEST_PRIORITY_TASK()这两个函函数的实现方法
taskSELECT_HIGHEST_PRIORITY_TASK():
这个函数的妙处就在于它并不是取下链表的第一个节点,而是每当调用一次这个函数,它的pxIndex指针就会向后移动一次。
假设当前链表有N个节点,当第N次调用该函数时,pxIndex则指向第N个节点,即每调用一次,节点遍历指针pxIndex则会向后移动一次,用于指向下一个节点。
taskRESET_READY_PRIORITY()函数的妙处在于清除优先级位图表uxTopReadyPriority中相应的位时候,会先判断当前优先级链表下是否还有其它任务,如果有则不清零。
4. 修改代码
修改xPortSysTickHandler():即当xTaskIncrementTick()函数返回为真时才进行任务切换,而原来的xTaskIncrementTick()是不带返回值的,执行到最后会调用taskYIELD()执行任务切换。
修改xTaskIncrementTick():将xTaskIncrementTick()函数修改成带返回值的函数,当有任务就绪且就绪任务的优先级比当前优先级高时,才执行一次任务切换,即将xSwitchRequired的值设置为pdTRUE。
5. 总结
其实FreeRTOS的这种时间片功能不能说是真正意义的时间片,因为它不能随意的设置时间为多少个tick,而是默认一个tick,然后默认在每个tick中断周期中进行任务切换而已。