任务接口
OpenOS 的任务管理系统负责创建、调度和管理内核和用户空间的执行单元。
/// 任务 ID#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]pub struct TaskId(u64);
/// 任务状态#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub enum TaskState { Ready, // 已创建,等待 CPU Running, // 正在 CPU 上执行 Blocked, // 等待 I/O 或 IPC Terminated, // 资源待回收}
/// 任务控制块pub struct Task { pub id: TaskId, pub name: String, pub state: TaskState, pub priority: u8,} ┌──────────┐ │ Ready │ ← 已创建,等待 CPU └────┬─────┘ │ schedule() ▼ ┌──────────┐ ┌────→│ Running │ ← 正在 CPU 上执行 │ └────┬─────┘ │ │ block() / yield() / exit() │ ▼ │ ┌──────────┐ │ │ Blocked │ ← 等待 I/O 或 IPC │ └────┬─────┘ │ │ wake() └──────────┘ │ exit() ▼ ┌──────────┐ │Terminated│ ← 资源待回收 └──────────┘OpenOS 使用轮询调度(Round-Robin)算法:
pub struct Scheduler { ready_queue: VecDeque<TaskId>, current_task: Option<TaskId>,}
impl Scheduler { pub fn schedule(&mut self) -> Option<TaskId> { // 从就绪队列取出下一个任务 let next = self.ready_queue.pop_front();
// 将当前任务放回队列(如果仍就绪) if let Some(current) = self.current_task { self.ready_queue.push_back(current); }
self.current_task = next; next }}| 特性 | 说明 |
|---|---|
| 算法 | 轮询(FIFO 队列) |
| 抢占 | 定时器中断(未来) |
| 量子 | 可配置(默认:1 个定时器 tick) |
| 空闲任务 | 始终存在于队列中,优先级 0,执行 hlt |
SYS_YIELD (4) - 让出 CPU
Section titled “SYS_YIELD (4) - 让出 CPU”主动将 CPU 让给调度器中的下一个任务。
参数: 无
返回值: 始终返回 0
使用场景:
- 协作式调度
- 等待事件时让出 CPU
- 实现用户态线程
示例:
mov rax, 4 ; SYS_YIELDsyscallSYS_EXIT (3) - 终止进程
Section titled “SYS_EXIT (3) - 终止进程”终止调用进程。内核回收所有资源。
参数:
| 参数 | 寄存器 | 类型 | 说明 |
|---|---|---|---|
| status | RDI | u64 | 退出码(0 = 成功) |
返回值: 不返回
示例:
; 正常退出mov rax, 3 ; SYS_EXITxor rdi, rdi ; 退出码 0syscall
; 错误退出mov rax, 3 ; SYS_EXITmov rdi, 1 ; 退出码 1syscall任务管理 API
Section titled “任务管理 API”/// 创建新任务pub fn create_task(name: &str, priority: u8) -> TaskId { let id = TaskId::new(); let task = Task { id, name: name.to_string(), state: TaskState::Ready, priority, };
// 添加到调度器 SCHEDULER.lock().add_task(id);
id}任务状态查询
Section titled “任务状态查询”/// 获取任务状态pub fn get_task_state(task_id: TaskId) -> Option<TaskState> { // 从任务表中查询 TASKS.lock().get(&task_id).map(|t| t.state)}
/// 获取当前任务 IDpub fn current_task_id() -> TaskId { CURRENT_TASK.lock().unwrap()}/// 阻塞当前任务pub fn block_task(reason: BlockReason) { let mut scheduler = SCHEDULER.lock(); if let Some(task_id) = scheduler.current_task { // 更新任务状态 TASKS.lock().get_mut(&task_id).unwrap().state = TaskState::Blocked;
// 从就绪队列移除 scheduler.remove_task(task_id); }}
/// 唤醒任务pub fn wake_task(task_id: TaskId) { let mut tasks = TASKS.lock(); if let Some(task) = tasks.get_mut(&task_id) { task.state = TaskState::Ready;
// 添加到就绪队列 SCHEDULER.lock().add_task(task_id); }}空闲任务是系统中始终存在的特殊任务:
/// 空闲任务fn idle_task() -> ! { loop { // 停止 CPU 直到下一个中断 x86_64::instructions::hlt(); }}特性:
- 优先级:0(最低)
- 状态:始终就绪
- 作用:当没有其他任务可运行时执行
定时器中断用于实现抢占式调度:
extern "x86-interrupt" fn timer_interrupt_handler( _stack_frame: InterruptStackFrame,) { // 增加系统 tick 计数 TICK_COUNT.fetch_add(1, Ordering::Relaxed);
// 检查是否需要调度 if should_schedule() { schedule(); }
// 发送 EOI unsafe { PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); }}| 事件 | 是否调度 | 说明 |
|---|---|---|
| 定时器中断 | 是 | 抢占式调度 |
| SYS_YIELD | 是 | 协作式调度 |
| 任务阻塞 | 是 | 切换到下一个就绪任务 |
| 任务唤醒 | 可选 | 取决于优先级 |
/// 任务优先级pub const PRIORITY_IDLE: u8 = 0; // 空闲任务pub const PRIORITY_LOW: u8 = 1; // 低优先级pub const PRIORITY_NORMAL: u8 = 5; // 普通优先级pub const PRIORITY_HIGH: u8 = 10; // 高优先级pub const PRIORITY_REALTIME: u8 = 15; // 实时优先级优先级调度算法
Section titled “优先级调度算法”impl Scheduler { pub fn schedule_by_priority(&mut self) -> Option<TaskId> { // 找到最高优先级的就绪任务 self.ready_queue .iter() .max_by_key(|id| { TASKS.lock().get(id).map(|t| t.priority).unwrap_or(0) }) .copied() }}通过 IPC 通信
Section titled “通过 IPC 通信”// 任务 A 发送消息给任务 Blet message = Message { sender: current_task_id(), receiver: task_b_port_id, data: MessageData::Text("Hello!".to_string()),};sys_send(task_b_port_id, &message)?;
// 任务 B 接收消息let mut buffer = [0u8; 1024];let received = sys_receive(task_b_port_id, &mut buffer)?;// 创建共享内存let shared_mem = sys_memory_create(4096, MEMORY_SHARED)?;
// 任务 A 映射let ptr_a = sys_memory_map(shared_mem, 0, 4096, 0, MAP_READ | MAP_WRITE)?;
// 任务 B 映射let ptr_b = sys_memory_map(shared_mem, 0, 4096, 0, MAP_READ | MAP_WRITE)?;
// 通过共享内存通信unsafe { core::ptr::write(ptr_a as *mut u64, 42); let value = core::ptr::read(ptr_b as *const u64);}| 功能 | 状态 | 说明 |
|---|---|---|
| 任务创建 | [done] 完成 | TaskId 原子生成 |
| 任务状态 | [done] 完成 | Ready/Running/Blocked/Terminated |
| 轮询调度 | [done] 完成 | FIFO 队列 |
| 空闲任务 | [done] 完成 | hlt 循环 |
| 优先级调度 | [WIP] 开发中 | 基本实现 |
| 抢占式调度 | [plan] 计划中 | 定时器中断 |
| 多核调度 | [plan] 计划中 | SMP 支持 |
查看任务状态
Section titled “查看任务状态”# 启用任务调试输出export OPENOS_TASK_DEBUG=1
# 运行内核make run-serial
# 查看任务日志[TASK] Created task 1 (idle) - Priority: 0[TASK] Created task 2 (init) - Priority: 5[TASK] Task 1 → Running[TASK] Task 1 → Ready (yield)[TASK] Task 2 → Running问题:任务饥饿
- 可能原因:高优先级任务占用 CPU
- 解决:实现老化机制,逐渐提高等待任务的优先级
问题:死锁
- 可能原因:循环等待资源
- 解决:使用超时或打破循环依赖