4、自适应调度核心概念:预算(budget)、周期(period)、关键度(criticality)

好,咱们今天来啃自适应调度里最核心的三个概念。预算、周期、关键度。这三个词,你光看字面意思可能觉得不难,但实际用起来,坑特别多。我当年第一次接触QNX自适应分区时,就栽在预算的理解上,差点把整个系统搞崩了。

说白了,这三个参数就是自适应调度的「三驾马车」。它们共同决定了每个分区能拿多少CPU时间、多久拿一次、以及关键时刻能不能抢别人的时间。咱们一个一个拆开讲。

4.1 预算(Budget)—— 你的时间额度

预算,就是QNX给每个分区分配的时间片。单位通常是微秒或毫秒。比如你给一个分区配了5ms的预算,那这个分区在每个周期里最多只能跑5ms。

嗯,这里要注意:预算不是「一次性给完」的。它是在每个周期开始时重置的。你跑完了,就得等下一个周期才能继续跑。

核心要点:预算 = 分区在每个周期内能使用的最大CPU时间。

我在项目中遇到过一个问题:有个音频处理分区,预算设了10ms,周期设了20ms。看起来挺合理对吧?但实际跑起来,音频偶尔会卡顿。后来一查,发现分区里有个任务偶尔会超时,把预算吃光了,导致后续任务没时间跑。

所以我的个人习惯是:预算不要设得太满。留点余量,比如预算设成周期的40%-45%,而不是50%。这样即使有小波动,系统也能扛得住。

避坑指南:我曾经把预算设得和周期一样大,结果分区直接占满了整个周期,其他分区全饿死了。记住,预算必须小于周期,否则调度器会出问题。

4.2 周期(Period)—— 你的时间节奏

周期,就是预算重置的时间间隔。比如周期是20ms,那每20ms,预算就会重新充满。

你想想看,周期决定了分区的「刷新频率」。周期越短,分区响应越快,但调度开销也越大。周期越长,调度开销小,但延迟会变大。

周期设置 优点 缺点
短周期(如1ms) 响应快,适合实时任务 调度开销大,CPU利用率低
长周期(如100ms) 调度开销小,吞吐量高 延迟大,不适合实时任务

我个人建议:周期要和任务的执行频率匹配。比如一个传感器采集任务每10ms采集一次数据,那周期就设10ms或略小于10ms。别设成100ms,否则数据都过期了才处理。

这里有个容易混淆的点:周期和预算的关系。预算 / 周期 = 分区能占用的CPU比例。比如预算5ms、周期20ms,那这个分区最多占25%的CPU。这个比例很重要,算错了整个系统的负载就失衡了。

注意:所有分区的预算之和不能超过周期。否则调度器无法保证所有分区都能按时拿到时间。我曾经见过一个团队把所有分区的预算加起来超过了周期,结果系统运行时分区之间互相抢时间,乱成一锅粥。

4.3 关键度(Criticality)—— 你的优先级护身符

关键度,是自适应调度里最特别的概念。它不像预算和周期那样是固定的数值,而是一个「等级」。通常分为低、中、高三级,或者用数字1、2、3表示。

关键度的作用是什么?说白了,就是当系统过载时,决定谁可以抢别人的时间。

举个例子:假设有两个分区,A分区关键度高,B分区关键度低。如果A分区把预算用完了,但还有紧急任务要跑,它就可以向调度器申请「借」B分区的时间。B分区如果也有任务在跑,就会被暂时挂起,等A跑完了再继续。

核心机制:关键度高的分区可以借用关键度低的分区的预算。但反过来不行。

我在项目中遇到过这样一个场景:有个安全相关的控制分区,关键度设成了高。另一个日志记录分区,关键度设成了低。平时两者相安无事。但有一次系统负载突然飙升,控制分区需要更多时间处理紧急事件。它二话不说就把日志分区的时间借走了。日志分区虽然慢了,但系统整体没崩溃。

这就是关键度的价值——保证最重要的任务永远有资源可用。

不过,关键度不是越高越好。你想想看,如果所有分区都设成高关键度,那这个机制就失效了。大家互相抢时间,谁也借不到谁的。

我的建议:关键度只给真正关键的分区设高。比如安全、控制、实时通信这些。普通的数据处理、日志、UI等,设成中或低就行。我曾经见过有人把所有分区都设成高关键度,结果系统过载时调度器直接懵了,谁都不让谁。

4.4 三者如何配合?

预算、周期、关键度,不是各自独立的。它们必须一起配置,才能发挥自适应调度的威力。

我一般这样配:

  1. 先定周期:根据任务的实时性要求,确定每个分区的周期。实时任务用短周期,非实时任务用长周期。
  2. 再算预算:根据任务的计算量,算出每个周期需要多少CPU时间。预算 = 任务执行时间 × 安全系数(1.2-1.5倍)。
  3. 最后设关键度:根据任务的重要性,分配关键度等级。只有最重要的任务才设高关键度。

举个例子,一个典型的配置:

分区A(安全控制):
  周期: 10ms
  预算: 4ms
  关键度: 高

分区B(数据采集):
  周期: 20ms
  预算: 5ms
  关键度: 中

分区C(日志记录):
  周期: 100ms
  预算: 10ms
  关键度: 低

这个配置里,安全控制分区每10ms能跑4ms,占40% CPU。如果它需要更多时间,可以借用B或C的时间。数据采集分区每20ms跑5ms,占25%。日志分区每100ms跑10ms,只占10%。总CPU占用75%,留了25%的余量。

嗯,这个余量很重要。我习惯留20%-30%的空闲CPU,用来应对突发负载。别把CPU跑满,否则系统稍微有点波动就出问题。

最后提醒:自适应调度不是万能的。它只能解决「预算不足但关键度高」的情况。如果所有分区都预算不足,系统还是会过载。所以,合理的预算规划才是根本。关键度只是最后的救命稻草。

好了,预算、周期、关键度这三个概念,咱们就聊到这。下一章我会讲如何在实际项目中配置这些参数,以及怎么用QNX工具监控它们的效果。到时候我会分享一些我踩过的坑,保证让你少走弯路。