4. INTEGRITY任务与分区模型
在 INTEGRITY 这类面向安全关键系统的实时操作系统中,任务(Task)是最小的可调度执行单元,而分区(Partition)是资源隔离与故障 containment 的基本单位。理解这两者的区别与联系,是掌握多核调度与资源隔离的起点。本节从任务与分区的定义出发,逐步展开地址空间、执行上下文、任务状态迁移,以及分区与任务之间的组织关系。
一、任务:调度的基本单位
任务是一个具有独立执行流的实体,它拥有自己的程序计数器、栈指针和寄存器组。在 INTEGRITY 中,任务通常由 Create_Task 或静态配置表创建,每个任务被赋予优先级、周期、执行时间预算等调度属性。任务可以处于多种状态,由内核调度器根据优先级和资源可用性进行切换。
任务的关键属性包括:
- 优先级:决定任务在就绪队列中的调度顺序,INTEGRITY 支持固定优先级抢占式调度。
- 周期与截止时间:对于周期性任务,定义其激活间隔和必须完成的时间点。
- 执行时间预算:任务在单个周期内允许消耗的最大 CPU 时间,超时会被内核挂起或终止。
- 入口函数与栈空间:任务开始执行的代码地址及其私有栈区域。
二、分区:资源隔离的容器
分区是一组任务的集合,它拥有独立的地址空间、独立的执行上下文,并在时间窗口和空间边界上与其他分区隔离。INTEGRITY 的分区模型遵循 ARINC 653 的时间分区与空间分区理念:每个分区在预定义的时间窗口内运行,窗口之外即使有就绪任务也不能占用 CPU;同时,分区只能访问自己的地址空间,无法读写其他分区的内存。
分区的核心属性包括:
- 分区 ID 与名称:用于标识和引用。
- 时间窗口:在主时间框架(Major Time Frame)中分配的起始偏移和持续时间。
- 地址空间基址与大小:由 MMU 或 MPU 保护的物理/虚拟内存区域。
- 分区模式:如冷启动、热启动、正常、空闲等。
三、地址空间与执行上下文
地址空间是分区隔离的空间维度。每个分区被分配一段独立的地址范围,内核通过 MMU 页表或 MPU 区域寄存器确保分区内的任务只能访问本分区内存。任务在分区内共享该地址空间,但每个任务仍有自己的栈和任务控制块(TCB)。
执行上下文是分区隔离的时间维度。它包含 CPU 寄存器组、程序状态字、栈指针以及分区相关的调度状态。当分区切换时,内核保存当前分区的执行上下文,恢复目标分区的执行上下文,从而实现分区之间的透明切换。执行上下文与地址空间共同构成分区的“隔离边界”。
四、任务状态迁移
INTEGRITY 中的任务状态通常包括:就绪(Ready)、运行(Running)、阻塞(Blocked)、挂起(Suspended)和终止(Terminated)。状态迁移由内核调度、任务自身调用或外部事件触发。
典型迁移路径如下:
- 任务创建后进入就绪状态,等待调度器选中。
- 被调度器选中后进入运行状态,开始执行。
- 运行中调用等待信号量、延时或等待事件时,进入阻塞状态。
- 阻塞条件满足后,重新回到就绪状态。
- 被显式挂起或分区时间窗口结束时,进入挂起状态。
- 任务执行完毕或被强制终止时,进入终止状态,资源被回收。
需要特别注意的是,在时间分区模型中,即使任务处于就绪状态,如果其所属分区的时间窗口未到,任务也不能运行。这是分区级调度与任务级调度叠加的结果。
五、分区与任务的关系
分区与任务之间是“容器与内容”的关系。一个分区可以包含一个或多个任务,这些任务共享分区的地址空间和时间窗口,但各自拥有独立的执行上下文和调度属性。分区内任务的调度由分区内的调度器负责,而分区之间的调度由内核的分区调度器负责。这种两级调度结构是 INTEGRITY 实现时间隔离的关键。
具体来说,分区与任务的关系体现在以下几个方面:
- 归属关系:每个任务必须属于且仅属于一个分区,任务不能跨分区迁移。
- 资源共享:同一分区内的任务共享该分区的地址空间、堆内存和分区级资源。
- 时间约束:分区的时间窗口决定了其内部任务可运行的时间范围,任务调度不能突破分区窗口。
- 故障隔离:一个分区内的任务故障(如越界访问、死循环)不会影响其他分区的任务,因为地址空间和时间窗口都是隔离的。
六、实践中的配置示例
以下是一个简化的 INTEGRITY 分区与任务配置示例,用于说明实际工程中如何组织这些对象。假设系统有两个分区:FlightControl 和 Display,主时间框架为 100ms。
Partition FlightControl {
Id = 1;
Duration = 40ms; // 时间窗口 40ms
Period = 100ms; // 主框架周期 100ms
Memory = 0x40000000, 2MB;
Tasks = {
Task AttitudeControl {
Priority = 10;
Period = 20ms;
ExecutionTime = 8ms;
Entry = &AttitudeControlMain;
},
Task Navigation {
Priority = 20;
Period = 50ms;
ExecutionTime = 5ms;
Entry = &NavigationMain;
}
};
}
Partition Display {
Id = 2;
Duration = 30ms;
Period = 100ms;
Memory = 0x50000000, 1MB;
Tasks = {
Task Render {
Priority = 15;
Period = 33ms;
ExecutionTime = 10ms;
Entry = &RenderMain;
}
};
}
在这个示例中,FlightControl 分区获得 40ms 的时间窗口,内部有两个任务:AttitudeControl 周期 20ms、执行时间 8ms,Navigation 周期 50ms、执行时间 5ms。在 40ms 窗口内,调度器需要安排这两个任务满足各自的周期和截止时间。如果 AttitudeControl 在 20ms 周期内执行 8ms,两个周期共 16ms,加上 Navigation 的 5ms,总需求 21ms,小于 40ms 窗口,因此可调度。若实际执行时间超出预算,内核会触发时间保护机制,挂起超时任务并记录错误。
Timeline 工具或 Schedule 视图观察每个分区的时间窗口占用情况,以及每个任务的实际执行时间。如果某个任务频繁超出预算,需要调整其优先级、周期或执行时间,或者重新划分分区窗口。
七、小结与关键理解
任务与分区是 INTEGRITY 调度模型的两个核心层次。任务关注“谁在运行”,分区关注“在哪里运行、什么时候运行”。地址空间和执行上下文分别从空间和时间两个维度定义了分区的隔离边界。任务状态迁移描述了任务在生命周期中的行为变化,而分区与任务的关系则决定了系统整体的可调度性和隔离性。理解这些概念,是后续学习多核调度、资源预算和故障恢复的基础。