调度器56—1-deadline文档翻译
注:本文翻译自 msm-5.4/Documentation/scheduler/sched-deadline.rst
=======================
Deadline任务调度
=======================
.. 内容
0. 警告
1. 概述
2. 调度算法
2.1 主要算法
2.2 带宽回收
3. 调度实时任务
3.1 定义
3.2 单处理器系统的可调度性分析
3.3 多处理器系统的可调度性分析
3.4 与SCHED_DEADLINE参数的关系
4. 带宽管理
4.1 系统范围设置
4.2 任务界面
4.3 默认行为
4.4 sched_yield() 的行为
5. 任务CPU亲和性
5.1 SCHED_DEADLINE 和 cpusets HOWTO
6. 未来计划
A. 测试套件
B. 最小 main()
0. 警告
=========
摆弄这些设置可能会导致不可预测甚至不稳定的系统行为。 至于-rt(组)调度,假设root用户知道他们在做什么。
1. 概述
===========
sched_dl 调度类中包含的 SCHED_DEADLINE 策略基本上是最早截止时间优先 (EDF) 调度算法的实现,并通过一种机制(称为恒定带宽服务,CBS)进行了增强,使得可以隔离任务之间的行为。
2. 调度算法
=======================
2.1 主要算法
------------------
SCHED_DEADLINE [18] 使用三个参数,名为“runtime”、“period”和“deadline”来调度任务。SCHED_DEADLINE 任务应该每“period”微秒获得执行时间“runtime”微秒,并且这些“runtime”微秒在周期开始后的“deadline”微秒内可用。 为了实现这个行为,每次任务唤醒时,调度器都会计算一个与保证一致的“scheduling deadline”(使用CBS[2,3]算法)。 然后在这些调度截止日期上使用 EDF[1] 来调度任务(选择具有最早调度截止日期的任务来执行)。 请注意,如果使用适当的“准入控制”策略(请参阅“4. 带宽管理”部分),任务实际上会在“deadline”内接收“runtime”时间(显然,如果系统过载,则无法遵守此保证)。
综上所述,CBS[2,3]算法为任务分配调度截止时间,以便每个任务在每个 period 最多运行其 runtime 时间,避免不同任务之间的任何干扰(带宽隔离),而EDF[1]算法则选择任务 将最早的调度截止时间作为下一个要执行的截止时间。 得益于此功能,不严格遵守“传统”实时任务模型(参见第 3 节)的任务可以有效地使用新策略。
更详细地说,CBS 算法通过以下方式为任务分配调度期限:
- 每个 SCHED_DEADLINE 任务由“runtime”、“deadline”和“period”参数来表征;
- 任务的状态由“调度截止时间”和“剩余运行时间”来描述。 这两个参数初始设置为0;
- 当 SCHED_DEADLINE 任务唤醒(准备好执行)时,调度程序检查是否:
remaining runtime runtime ---------------------------------- > --------- scheduling deadline - current time period
然后,如果调度截止时间小于当前时间,或者验证了该条件,则调度截止时间和剩余运行时间被重新初始化为:
scheduling deadline = current time + deadline
remaining runtime = runtime
否则,调度截止时间和剩余运行时间保持不变;
- 当 SCHED_DEADLINE 任务执行时间 t 时,其剩余运行时间减少为:
remaining runtime = remaining runtime - t
(从技术上讲,运行时间在每次tick时或在任务被取消调度/抢占时都会减少);
- 当剩余运行时间变得小于或等于 0 时,该任务被称为“throttled”(在实时文献中也称为“depleted”),并且在其调度截止日期之前无法进行调度。 该任务的“补充时间”(见下一项)设置为等于调度截止时间的当前值;
- 当当前时间等于throttled任务的补充时间时,调度截止时间和剩余运行时间更新为:
scheduling deadline = scheduling deadline + period
remaining runtime = remaining runtime + runtime
sched_attr 的 sched_flags 字段中的 SCHED_FLAG_DL_OVERRUN 标志允许任务通过传递 SIGXCPU 信号来了解运行时溢出情况。
2.2 带宽回收
------------------------
deadline任务的带宽回收基于 GRUB(未使用带宽的贪婪回收)算法 [15,16,17],并且在设置标志 SCHED_FLAG_RECLAIM 时启用。
下图说明了 GRUB 处理的任务的状态名称:
------------ (d) | Active | ------------->| | | | Contending | | ------------ | A | ---------- | | | | | | | Inactive | |(b) | (a) | | | | ---------- | | A | V | ------------ | | Active | --------------| Non | (c) | Contending | ------------
任务可以处于以下状态之一:
- ActiveContending:是否准备好执行(或正在执行);
- ActiveNonContending:如果刚刚阻塞并且尚未超过 0-lag 时间;
- Inactive: 如果被阻塞并且超过了 0 滞后时间。
状态转换:
(a) 当任务阻塞时,它不会立即变为不活动状态,因为在不破坏实时保证的情况下无法立即回收其带宽。 因此,它进入称为 ActiveNonContending 的过渡状态。 调度程序将“inactive timer”设置为在 0 延迟时间触发,此时可以在不破坏实时保证的情况下回收任务的带宽。
任务进入 ActiveNonContending 状态的 0 延迟时间计算如下:
(runtime * dl_period) deadline - --------------------- dl_runtime
其中 runtime 是剩余运行时间,而 dl_runtime 和 dl_period 是预留参数。
(b) 如果任务在 inactive timer 触发之前唤醒,则任务重新进入 ActiveContending 状态,并且“inactive timer”被取消。 此外,如果任务在不同的运行队列上唤醒,则必须从先前运行队列的活动利用率中删除该任务的利用率,并且必须将其添加到新运行队列的活动利用率中。 为了避免在“inactive timer”在不同 CPU 上运行时在运行队列上唤醒的任务之间发生竞争,“dl_non_contending”标志用于指示任务不在运行队列上但处于活动状态(因此, 标志在任务阻塞时设置,并在“inactive timer”触发或任务唤醒时清除)。
(c) 当“inactive timer”触发时,任务进入非活动状态,并且其利用率将从运行队列的活动利用率中删除。
(d) 当非活动任务唤醒时,它进入 ActiveContending 状态,并且其利用率将添加到它已入队的运行队列的活动利用率中。
对于每个运行队列,GRUB 算法会跟踪两个不同的带宽:
- 活动带宽(running_bw):这是处于活动状态(即 ActiveContending 或 ActiveNonContending)的所有任务的带宽总和;
- 总带宽 (this_bw):这是“属于”运行队列的所有任务的总和,包括处于非活动状态的任务。
该算法回收处于非活动状态的任务的带宽。 它通过以等于的速度减少执行任务 Ti 的运行时间来实现这一点
dq = -max{ Ui / Umax, (1 - Uinact - Uextra) } dt
其中:
- Ui 是任务 Ti 的带宽;
- Umax 是最大可回收利用率(受RT节流限制);
- Uinact 是(每个运行队列)非活动利用率,计算方式为 (this_bq - running_bw);
- Uextra 是(每个运行队列)额外的可回收利用率(受 RT 限制)。
现在让我们看一个简单的示例,其中两个deadline任务的 runtime 等于 4,period 等于 8(即带宽等于 0.5):
A Task T1 | | | | | |-------- |---- | | V |---|---|---|---|---|---|---|---|--------->t 0 1 2 3 4 5 6 7 8 A Task T2 | | | | | | ------------------------| | | V |---|---|---|---|---|---|---|---|--------->t 0 1 2 3 4 5 6 7 8 A running_bw | 1 ----------------- ------ | | | 0.5- ----------------- | | |---|---|---|---|---|---|---|---|--------->t 0 1 2 3 4 5 6 7 8
- 时间 t = 0:
两个任务都已准备好执行,因此处于 ActiveContending 状态。 假设任务 T1 是第一个开始执行的任务。 由于没有不活动的任务,因此其运行时间减少为 dq = -1 dt。
- 时间 t = 2:
假设任务 T1 阻塞,因此任务 T1 进入 ActiveNonContending 状态。 由于其剩余运行时间等于 2,其 0 滞后时间等于 t = 4。任务 T2 开始执行,运行时间仍减少为 dq = -1 dt,因为没有非活动任务。
- 时间 t = 4:
这是任务 T1 的 0 滞后时间。 由于它在此期间没有被唤醒,因此它进入 Inactive 状态。 其带宽已从 running_bw 中删除。
任务 T2 继续执行。 然而,它的运行时间现在减少了 dq = - 0.5 dt 因为 Uinact = 0.5。
因此,任务 T2 回收任务 T1 未使用的带宽。
- 时间 t = 8:
任务 T1 醒来。 再次进入 ActiveContending 状态,running_bw 递增。
2.3 能源感知调度
----------------------------
当选择 cpufreq 的 schedutil 调控器时,SCHED_DEADLINE 实现 GRUB-PA [19] 算法,将 CPU 运行频率降低到仍能满足截止时间的最小值。 目前,此行为仅针对 ARM 架构实现。
必须特别小心,以防更改频率所需的时间与保留周期具有相同的数量级。 在这种情况下,设置固定的 CPU 频率可以减少最后期限错过的数量。
3. 调度实时任务
=============================
.. 大胖警告 ************************************************* *********
.. 警告::
本节包含对经典deadline调度理论及其如何应用于 SCHED_DEADLINE 的(不彻底)总结。 如果读者只想了解如何使用调度策略,则可以“安全”地跳至第 4 节。 不管怎样,我们强烈建议回到这里并继续阅读(一旦满足了测试的冲动:P),以确保完全理解所有技术细节。
.. ************************************************************************
对于什么样的任务可以利用这种新的调度规则没有限制,即使必须说它特别适合需要保证其定时行为的周期性或零星实时任务,例如多媒体、流媒体、控制 应用程序等
3.1 定义
------------------------
典型的实时任务由重复的计算阶段(任务实例或作业)组成,这些阶段以周期性或零星的方式激活。
每个作业 J_j(其中 J_j 是任务的第 j^th 个作业)的特征是到达时间 r_j(作业开始的时间)、完成作业所需的计算时间量 c_j 以及作业绝对期限 d_j ,这是作业应该完成的时间。 最大执行时间 max{c_j} 称为任务的“最坏情况执行时间”(WCET)。 如果 r_{j+1} = r_j + P,则实时任务可以是周期为 P 的周期性任务;如果 r_{j+1} = r_j + P,则实时任务可以是周期性任务;如果 r_{j+1} >= r_j + P,则实时任务可以是具有最小到达间隔时间 P 的零星任务。最后,d_j = r_j + D,其中 D 是任务的相对截止日期。 总结一下,实时任务可以描述为
Task = (WCET, D, P)
实时任务的利用率定义为其 WCET 与其周期(或最小到达间隔时间)之间的比率,表示执行任务所需的 CPU 时间的比例。
如果总利用率 U=sum(WCET_i/P_i) 大于 M(其中 M 等于 CPU 数量),则调度程序无法遵守所有期限。
请注意,总利用率定义为系统中所有实时任务的利用率 WCET_i/P_i 之和。 当考虑多个实时任务时,第i个任务的参数用“_i”后缀表示。
此外,如果总利用率大于 M,那么我们就面临着实时任务让非实时任务挨饿的风险。 相反,如果总利用率小于 M,则非实时任务将不会挨饿,并且系统可能能够遵守所有截止日期。
事实上,在这种情况下,可以为迟到提供一个上限(定义为 0 与作业完成时间与其绝对截止日期之间的差值之间的最大值)。 更准确地说,可以证明使用全局 EDF 调度器,每个任务的最大延迟小于或等于
((M − 1) · WCET_max − WCET_min)/(M − (M − 2) · U_max) + WCET_max
其中 WCET_max = max{WCET_i} 是最大 WCET,WCET_min=min{WCET_i} 是最小 WCET,U_max = max{WCET_i/P_i} 是最大利用率[12]。
3.2 单处理器系统的可调度性分析
-------------------------------------------------- --
如果 M=1(单处理器系统),或者在分区调度的情况下(每个实时任务静态分配给一个且仅一个 CPU),则可以正式检查是否遵守所有截止时间。 如果所有任务的 D_i = P_i,则当且仅当在 CPU 上运行的任务的总利用率小于或等于 1 时,EDF 才能够遵守在 CPU 上执行的所有任务的所有截止时间。如果 D_i ! = P_i 对于某些任务,则可以将任务的密度定义为 WCET_i/min{D_i,P_i},并且 EDF 能够遵守 CPU 上运行的所有任务的所有截止日期,如果密度之和 在这样的CPU上运行的任务的数量小于或等于1:
sum(WCET_i / min{D_i, P_i}) <= 1
值得注意的是,这个条件只是充分的,而不是必要的:有些任务集是可调度的,但不遵守该条件。 例如,考虑由 Task_1=(50ms,50ms,100ms)和 Task_2=(10ms,100ms,100ms)组成的任务集{Task_1,Task_2}。 EDF 显然能够在不错过任何截止日期的情况下调度这两个任务(Task_1 在发布后立即调度,并及时完成以遵守其截止日期;Task_2 在 Task_1 之后立即调度,因此其响应时间不能大于 50ms + 10ms = 60ms) 即使
50 / min{50,100} + 10 / min{100, 100} = 50 / 50 + 10 / 100 = 1.1
当然,可以用 D_i != P_i 来测试任务的精确可调度性(检查充分且必要的条件),但这不能通过将总利用率或密度与常数进行比较来完成。 相反,可以使用所谓的“处理器需求”方法,计算所有任务在大小为 t 的时间间隔内遵守其所有截止日期所需的 CPU 时间总量 h(t),并将该时间与间隔大小 t。 如果对于 t 的所有可能值,h(t) 都小于 t(即,在大小为 t 的时间间隔内任务所需的时间量小于间隔的大小),则 EDF 能够尊重所有截止日期安排任务。 由于对 t 的所有可能值执行此检查是不可能的,因此已证明 [4,5,6] 对 0 和最大值 L 之间的 t 值执行测试就足够了。引用的论文包含所有 数学细节并解释如何计算 h(t) 和 L。无论如何,这种分析过于复杂且耗时,无法在线执行。 因此,如第 4 节中所述,Linux 使用基于任务利用率的准入测试。
3.3 多处理器系统的可调度性分析
-----------------------------------------------------
在具有全局 EDF 调度的多处理器系统(非分区系统)上,对可调度性的充分测试不能基于利用率或密度:可以证明,即使利用率略大于 1 的 D_i = P_i 任务集也可能会错过最后期限 CPU 数量。
考虑具有 M 个 CPU 的系统上的 M+1 个任务的集合 {Task_1,...Task_{M+1}},第一个任务 Task_1=(P,P,P) 的周期、相对截止时间和 WCET 等于 P.剩余的M个任务 Task_i=(e,P-1,P-1) 具有任意小的最坏情况执行时间(这里表示为“e”)并且周期小于第一个任务的周期。 因此,如果所有任务在同一时间 t 激活,则全局 EDF 首先调度这 M 个任务(因为它们的绝对期限等于 t + P - 1,因此它们小于 Task_1 的绝对期限,即 t + P )。 因此,Task_1 只能在时间 t + e 处调度,并将在其绝对截止时间之后的时间 t + e + P 处完成。 任务集的总利用率为 U = M·e / (P - 1) + P / P = M·e / (P - 1) + 1,对于较小的 e 值,这可能会变得非常接近 1。 这被称为“达尔效应”[7]。 注意:Dhall 原始论文中的示例已在此稍微简化(例如,Dhall 更正确地计算 lim_{e->0}U)。
实时文献[8,9]中已经开发了更复杂的全局 EDF 可调度性测试,但它们并不是基于总利用率(或密度)与固定常数之间的简单比较。 如果所有任务都有D_i = P_i,则充分的可调度性条件可以用简单的方式表示:
sum(WCET_i / P_i) <= M - (M - 1) · U_max
其中 U_max = max{WCET_i / P_i}[10]。 请注意,对于 U_max = 1,M - (M - 1) · U_max 变为 M - M + 1 = 1,并且此可调度性条件恰好证实了 Dhall 的效果。 关于多处理器实时调度的可调度性测试的文献的更完整的调查可以在[11]中找到。
可以看出,强制总利用率小于 M 并不能保证全局 EDF 调度任务时不会错过任何截止时间(换句话说,全局 EDF 不是最优调度算法)。 然而,小于M的总利用率足以保证非实时任务不会挨饿,并且实时任务的延迟有一个上限[12](如前所述)。 各种论文[13,14]对实时任务所经历的最大延迟提出了不同的界限,但对于 SCHED_DEADLINE 重要的理论结果是,如果总利用率小于或等于 M,则响应时间 任务是有限的。
3.4 与SCHED_DEADLINE参数的关系
-----------------------------------------------------------
最后,了解第 2 节中描述的 SCHED_DEADLINE 调度参数(runtime、deadline 和 period)与本节中描述的实时任务参数(WCET、D、P)之间的关系非常重要。 请注意,任务的时间约束由上述绝对期限 d_j = r_j + D 表示,而 SCHED_DEADLINE 根据调度期限来调度任务(参见第 2 节)。
如果使用准入测试来保证遵守调度最后期限,则可以使用 SCHED_DEADLINE 来调度实时任务,以保证遵守任务的所有作业的最后期限。 为此,必须通过设置来安排任务:
- runtime >= WCET - deadline = D - period <= P
IOW,如果 runtime >= WCET 并且 period <= P,则调度截止时间和绝对截止时间 (d_j) 重合,因此适当的准入控制允许尊重作业对该任务的绝对截止时间(这就是所谓的) “硬可调度性属性”,是 [2] 的引理 1 的扩展。 请注意,如果 runtime > deadline,准入控制肯定会拒绝该任务,因为不可能遵守其时间约束。
参考:
......
4. 带宽管理
=======================
如前所述,为了使截止日期调度有效且有用(即能够在“deadline”内提供“runtime”时间单位),重要的是要有某种方法来保持可用分数的分配控制下的各种任务的 CPU 时间。 这通常称为“准入控制”,如果不执行,则无法保证截止日期任务的实际调度。
正如第 3 节中已经提到的,正确调度一组实时任务需要满足的一个必要条件是总利用率小于 M。当谈论截止日期任务时,这要求运行时之间的比率之和 所有任务的周期都小于 M。请注意,运行时间/周期的比率相当于“传统”实时任务的利用率,并且通常也称为“带宽”。
用于控制可分配给 -deadline 任务的 CPU 带宽的接口类似于已用于具有实时组调度的 -rt 任务的接口(也称为 RT throttling - 请参阅 Documentation/scheduler/sched-rt-group)。 rst),并且基于位于 procfs 中的可读/可写控制文件(用于系统范围的设置)。 请注意,仍然没有为 -deadline 任务定义每组设置(通过 cgroupfs 控制),因为需要进行更多讨论才能弄清楚我们希望如何在任务组级别管理 SCHED_DEADLINE 带宽。
截止日期带宽管理和 RT 节流之间的主要区别在于 -deadline 任务有自己的带宽(而 -rt 任务则没有!),因此我们不需要更高级别的节流机制来强制执行所需的带宽。 换句话说,这意味着接口参数仅在准入控制时使用(即,当用户调用 sched_setattr() 时)。 然后根据实际任务的参数进行调度,以便根据粒度需求将 CPU 带宽分配给 SCHED_DEADLINE 任务。 因此,使用这个简单的接口,我们可以对截止日期任务的总利用率设置上限(即 \Sum (runtime_i / period_i) < global_dl_utilization_cap)。
4.1 系统范围设置
------------------------
系统范围的设置在 /proc 虚拟文件系统下配置。
目前,-rt 旋钮用于 -deadline 准入控制,并且 -deadline 运行时间根据 -rt 运行时间进行计算。 我们意识到这并不完全是可取的; 不过,目前最好有一个小界面,以便以后能够轻松更改。 理想的情况(参见图 5)是从 -deadline 服务器运行 -rt 任务; 在这种情况下,-rt 带宽是 dl_bw 的直接子集。
这意味着,对于包含 M 个 CPU 的 root_domain,可以创建截止期限任务,同时其带宽总和保持在以下水平:
M * (sched_rt_runtime_us / sched_rt_period_us)
还可以禁用此带宽管理逻辑,从而避免系统超额订阅达到任意级别。 这是通过在 /proc/sys/kernel/sched_rt_runtime_us 中写入 -1 来完成的。
4.2 任务界面
------------------
指定在每个实例上执行给定运行时间的周期性/偶发任务,并且根据其自身定时约束的紧急程度进行调度,通常需要一种声明方式:
- (最大/典型)实例执行时间,
- 连续实例之间的最小间隔,
- 每个实例必须完成的时间限制。
所以:
* 提供了一个新的 struct sched_attr,其中包含所有必要的字段;
* 实现了操纵它的新调度相关系统调用,即 sched_setattr() 和 sched_getattr()。
出于调试目的,可以通过 /proc/<pid>/sched 检索 SCHED_DEADLINE 任务的剩余运行时间和绝对截止时间(条目 dl.runtime 和 dl.deadline,这两个值均以 ns 为单位)。正在讨论一种从生产代码中检索这些值的编程方法。
4.3 默认行为
--------------------
SCHED_DEADLINE 带宽的默认值是让 rt_runtime 等于 950000。默认情况下,当 rt_period 等于 1000000 时,这意味着对于每个 root_domain,-deadline 任务最多可以使用 95%(乘以组成 root_domain 的 CPU 数量) 。
这意味着非deadline任务将获得至少 5% 的 CPU 时间,而deadline任务将接收其运行时间,并保证相对于“截止日期”参数的最坏情况延迟。 如果“deadline”=“period”并且使用cpuset机制来实现分区调度(参见第5节),那么这种简单的带宽管理设置就能够确定性地保证-deadline任务将在一个周期内收到其运行时间。
最后,请注意,为了不危害准入控制,-deadline 任务不能 fork。
4.4 sched_yield() 的行为
----------------------------
当 SCHED_DEADLINE 任务调用 sched_yield() 时,它会放弃剩余的运行时间并立即被限制,直到下一个周期,此时其运行时间将被补充(设置一个特殊标志 dl_yielded 并用于在调用后正确处理限制和运行时补充) 到 sched_yield())。
sched_yield() 的这种行为允许任务在下一个周期开始时准确唤醒。 此外,这在未来的带宽回收机制中可能很有用,其中 sched_yield() 将使剩余的 runtime 用于其他 SCHED_DEADLINE 任务的回收。
5. 任务CPU亲和性
=====================
-deadline 任务的关联掩码不能小于创建它们的整个 root_domain。 但是,可以通过 cpuset 工具指定关联性 (Documentation/admin-guide/cgroup-v1/cpusets.rst)。
5.1 SCHED_DEADLINE 和 cpusets HOWTO
------------------------------------------------
下面是一个简单配置的示例(将 -deadline 任务固定到 CPU0)(rt-app 用于创建 -deadline 任务):
mkdir /dev/cpuset mount -t cgroup -o cpuset cpuset /dev/cpuset cd /dev/cpuset mkdir cpu0 echo 0 > cpu0/cpuset.cpus echo 0 > cpu0/cpuset.mems echo 1 > cpuset.cpu_exclusive echo 0 > cpuset.sched_load_balance echo 1 > cpu0/cpuset.cpu_exclusive echo 1 > cpu0/cpuset.mem_exclusive echo $$ > cpu0/tasks rt-app -t 100000:10000:d:0 -D5 # 现在指定任务亲和力实际上是多余的
6. 未来计划
===============
仍然失踪:
- 以编程方式检索当前运行时间和绝对期限。
- 对截止时间继承的改进,特别是关于在非交互任务之间保留带宽隔离的可能性。 我们正在从理论和实践的角度对此进行研究,希望我们能够很快产生一些演示代码;
- (c)基于组的带宽管理,以及可能的调度;
- 对非root用户的访问控制(以及相关的安全问题需要解决),这是允许非特权使用的最佳机制以及如何防止非root用户“欺骗”系统?
正如已经讨论过的,我们还计划将这项工作与 EDF 节流补丁合并 [https://lkml.org/lkml/2010/2/23/239],但我们仍处于合并的初步阶段,我们确实 寻求反馈,帮助我们决定应该采取的方向。
附录 A. 测试套件
=====================
SCHED_DEADLINE 策略可以使用两个应用程序轻松测试,这两个应用程序是更广泛的 Linux 调度程序验证套件的一部分。 该套件可作为 GitHub 存储库提供:https://github.com/scheduler-tools。
第一个测试应用程序称为 rt-app,可用于启动具有特定参数的多个线程。 rt-app 支持 SCHED_{OTHER,FIFO,RR,DEADLINE} 调度策略及其相关参数(例如,niceness、priority、runtime/deadline/period)。 rt-app 是一个很有价值的工具,因为它可用于综合地重新创建某些工作负载(可能模仿真实的用例)并评估调度程序在此类工作负载下的行为方式。 通过这种方式,结果很容易重现。 rt-app 位于:https://github.com/scheduler-tools/rt-app。
# rt-app -t 100000:10000:d -t 150000:20000:f:10 -D5
上面创建了 2 个线程。 第一个由 SCHED_DEADLINE 调度,每 100 毫秒执行 10 毫秒。 第二个调度为 SCHED_FIFO 优先级 10,每 150 毫秒执行 20 毫秒。 测试总共将运行 5 秒。
更有趣的是,配置可以使用 json 文件来描述,该文件可以作为输入传递给 rt-app,如下所示:
# rt-app my_config.json
可以使用第二种方法指定的参数是命令行选项的超集。 请参阅 rt-app 文档了解更多详细信息 (`<rt-app-sources>/doc/*.json`)。
第二个测试应用程序是 schedtool 的修改版,称为 schedtool-dl,可用于为特定 pid/应用程序设置 SCHED_DEADLINE 参数。 schedtool-dl 位于:https://github.com/scheduler-tools/schedtool-dl.git。
用法很简单::
# schedtool -E -t 10000000:100000000 -e ./my_cpuhog_app
这样,my_cpuhog_app 就会在每 100 毫秒 10 毫秒的 SCHED_DEADLINE 预留内运行(请注意,参数以微秒表示)。 您还可以使用 schedtool 为已运行的应用程序创建预留,前提是您知道其 pid::
# schedtool -E -t 10000000:100000000 my_app_pid
附录 B. 最小 main()=========================
我们在下文中提供了一个简单(丑陋)的独立代码片段,展示了实时应用程序开发人员如何创建 SCHED_DEADLINE 预订:
...
总结:
1. 为了不危害准入控制,-deadline 任务不能 fork。
posted on 2024-03-05 17:36 Hello-World3 阅读(151) 评论(0) 编辑 收藏 举报