FreeRTOS 学习:(二十七)死等延时函数会对任务调度产生什么影响

上一篇 下一篇
FreeRTOS 专用延时函数

死等延时函数会对任务调度产生什么影响

首先,死等延时函数指的是 忙等待(Busy Wait) ,典型形式是 delay_ms(100) ,具体参考函数如下:

c 复制代码
/**
 * @brief       延时nus
 * @param       nus: 要延时的us数.
 * @note        nus取值范围: 0 ~ 477218588(最大值即2^32 / g_fac_us @g_fac_us = 9)
 * @retval      无
 */
void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload;
    
    reload = SysTick->LOAD;     /* LOAD的值 */
    ticks = nus * g_fac_us;     /* 需要的节拍数 */
    told = SysTick->VAL;        /* 刚进入时的计数器值 */

    while (1)
    {
        tnow = SysTick->VAL;

        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;    /* 这里注意一下SYSTICK是一个递减的计数器就可以了. */
            }
            else
            {
                tcnt += reload - tnow + told;
            }

            told = tnow;

            if (tcnt >= ticks) break;   /* 时间超过/等于要延迟的时间,则退出. */
        }
    }
}

/**
 * @brief       延时nms
 * @param       nms: 要延时的ms数 (0< nms <= 65535)
 * @retval      无
 */
void delay_ms(uint16_t nms)
{
    uint32_t i;

    for (i=0; i<nms; i++)
    {
        delay_us(1000);
    }
}

它的本质是:CPU 一直卡在当前任务,不做"有意义的事"

调用死等延时函数的任务在整个等待期间:

  • 始终处于 Running / Ready 状态
  • 不主动进入 Blocked
  • 持续占用 CPU 执行空循环

1)对抢占式任务调度的影响

若该任务优先级较高,当其 "霸占CPU" 时:

  • 调度器没有机会切换到低优先级任务
  • 低优先级任务被长期甚至永久饿死,此时即便低优先级任务 Ready,也无法获得执行机会。

若该任务优先级较低,当其 "霸占CPU" 时:

  • 即使低优先级任务在死等,只要 PendSV 中断没关,高优先级任务照样能抢占,被抢占的低优先级任务会在高优先级任务阻塞时,继续执行未结束的死等延时。
  • 但如果这个死等延时函数中,涉及到关中断了,那么高优先级任务也无法抢占在执行死等延时的低优先级任务

2)对时间片轮转式任务调度的影响

时间片调度适用于 相同优先级 且处于 Ready 状态的多个任务,当某个任务存在死等延时的情况下:

  • 死等延时这部分时间,CPU 被浪费;
  • SysTick 中断没关的话,时间片轮转一般不会受到影响,时间片到了之后,依旧会切换到下一个任务(只是说由于之前有一部分时间被浪费了,所以下一个任务需要等满一整个时间片才会被执行,不过这也不是一定的,有可能死等延时任务会占用更多的CPU);
  • 如果时间片到了的时候,上一个任务中的死等延时还没结束,会被系统将状态保存下来,等到下一个时间片轮到这个任务的时候,继续死等。
  • 但如果这个死等延时函数中,涉及到关中断了,那么时间片轮转会被严重影响,任务无法切换

举例:

假设一个时间片 = 1 ms,TaskA、TaskB 同优先级,死等不关中断、不阻塞。

TaskA 每轮逻辑:600 μs 有效执行 + 600 μs 死等;

TaskB 每轮逻辑:1ms 有效执行。

则严格的时间推演为:

c 复制代码
0 ~ 600 μs 			--> 	TaskA 有效执行
600 ~ 1000 μs 		--> 	TaskA 死等(结束后剩余200μs)
1000μs ~ 2000 μs 	--> 	TaskB 有效执行
2000 ~ 2200 μs 		--> 	TaskA 继续死等
2200μs ~ 2800 μs 	--> 	TaskA 有效执行
2800 ~ 3000 μs 		--> 	TaskA 死等(结束后剩余400μs)
3000μs ~ 4000 μs 	--> 	TaskB 有效执行
......

相关推荐
2501_918126914 小时前
野火stm32怎么玩
stm32·单片机·生活·个人开发
2501_918126914 小时前
stm32能做次声波检测器吗?
c语言·stm32·单片机·嵌入式硬件·学习
LCG元6 小时前
多电机同步控制:STM32F7+CAN总线,工业纺纱机应用实战
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi6 小时前
基于5G的车辆跟驰预警系统(论文+源码)
stm32·单片机·5g·毕业设计
_OP_CHEN9 小时前
【Linux系统编程】(三十九)吃透线程概念:从底层原理到实战应用
linux·运维·操作系统·线程·进程·多线程·c/c++
LCG元16 小时前
STM32MP1边缘网关:Linux系统下Modbus转MQTT协议转换实战
linux·stm32·嵌入式硬件
2501_9181269121 小时前
stm32核心板是什么属性?
linux·c语言·stm32·嵌入式硬件·个人开发
何中应21 小时前
解决Windows CMD中文乱码问题
windows·操作系统
何中应1 天前
Windows打开命令窗口的几种方式
windows·操作系统