ax-task
路径:
os/arceos/modules/axtask类型:库 crate 分层:ArceOS 层 / ArceOS 内核模块 版本:0.3.0-preview.3文档依据:Cargo.toml、README.md、src/lib.rs、src/api.rs、src/task.rs、src/run_queue.rs、src/wait_queue.rs、src/timers.rs、src/future/*
ax-task 是 ArceOS 的任务管理核心模块。它既承担线程/任务对象的创建、阻塞、退出与回收,又通过 axsched 抽象把 FIFO、RR、CFS 等调度策略统一到同一个运行队列框架下,并进一步向 StarryOS 和 Axvisor 输出可复用的调度基础设施。
架构设计
1.1 总体设计
ax-task 的设计目标不是提供“单一线程库”,而是构造一个可裁剪的内核任务运行时:
- 通过
multitaskfeature 在“真正多任务调度器”和“单任务桩实现”之间切换。 - 通过
sched-fifo、sched-rr、sched-cfs在同一套 API 下选择不同调度策略。 - 通过
irq、preempt、smp、tls、task-ext决定任务系统究竟具备多少内核能力。
因此,ax-task 是一个强 feature 驱动的状态机模块,而不是简单的 API 封装。
模块结构
src/lib.rs:顶层 feature 门控。决定编译run_queue、task、api、wait_queue、future、timers还是退回api_s单任务实现。src/task.rs:任务实体定义与状态机,包含TaskInner、TaskState、CurrentTask、栈对象、退出码、join 与可选 TLS/TaskExt 字段。src/run_queue.rs:每 CPU 运行队列、调度切换、GC 任务、SMP 下多队列初始化与迁移逻辑。src/api.rs:多任务模式下的公开 API,如spawn()、yield_now()、sleep()、exit()、set_priority()、set_current_affinity()等。src/api_s.rs:单任务模式下的桩实现,很多“阻塞”行为会退化为 busy-wait 或等待 IRQ。src/wait_queue.rs:基于event-listener的等待队列封装。src/timers.rs:IRQ 打开时的定时事件回调与每核计时事件检查。src/future/mod.rs:内核态block_on、waker、阻塞/唤醒桥接。src/future/time.rs:截止时间驱动的 sleep/timeout future 与每核TimerRuntime。src/future/poll.rs:I/O poll 异步适配,与axpoll协作。src/tests.rs:FIFO、浮点状态切换、WaitQueue、join等单元测试。
1.3 关键数据结构
TaskState:Running、Ready、Blocked、Exited,是任务生命周期分析的核心。TaskInner:任务内部主体,包含任务名、entry 闭包、上下文、栈、退出码、等待退出事件、CPU 亲和、可选 TLS、可选TaskExt等。CurrentTask:当前任务句柄,是 API 层访问当前任务状态、优先级、亲和性和扩展对象的主要入口。AxTaskRef/WeakAxTaskRef:调度器持有的任务引用类型。AxRunQueue:每 CPU 运行队列包装,内部持有具体Scheduler实例并负责上下文切换。WaitQueue:内核阻塞/唤醒的基础同步原语。TimerRuntime:基于截止时间和 waker 的软件定时运行时,仅在irq路径启用。AxTaskExt/TaskExt:供上层系统附加任务私有语义的扩展接口,是 StarryOS 线程对象与 Axvisor vCPU 任务集成的关键点。
1.4 调度器抽象与算法实现
ax-task 并不自己实现完整调 度算法,而是通过 api.rs 中的类型别名把 TaskInner 适配到 axsched:
sched-fifo:FifoScheduler+FifoTask,协作式调度。sched-rr:RRScheduler+RRTask,带时间片,依赖preempt。sched-cfs:CFScheduler+CFSTask,公平调度,同样依赖preempt。
这层设计的关键好处是:
TaskInner始终保持稳定。- 上层 API 如
spawn、yield_now、sleep无需感知底层采用 FIFO、RR 还是 CFS。 - StarryOS、Axvisor 可以在不重写任务核心对象的前提下复用调度机制。
1.5 任务生命周期主线
典型生命周期可概括为:
更具体的初始化主线如下:
init_scheduler()调用run_queue::init()。- 主 CPU 创建 idle 任务、当前 init 任务和 GC 任务。
spawn_task()/spawn()把新任务加入选中的运行队列。yield_current()、blocked_resched()、scheduler_timer_tick()驱动状态在Running/Ready/Blocked间转换。exit_current()把任务移入退出队列,由 GC 任务清理最终资源。