跳转到内容

任务接口

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

主动将 CPU 让给调度器中的下一个任务。

参数:

返回值: 始终返回 0

使用场景:

  • 协作式调度
  • 等待事件时让出 CPU
  • 实现用户态线程

示例:

mov rax, 4 ; SYS_YIELD
syscall

终止调用进程。内核回收所有资源。

参数:

参数寄存器类型说明
statusRDIu64退出码(0 = 成功)

返回值: 不返回

示例:

; 正常退出
mov rax, 3 ; SYS_EXIT
xor rdi, rdi ; 退出码 0
syscall
; 错误退出
mov rax, 3 ; SYS_EXIT
mov rdi, 1 ; 退出码 1
syscall
/// 创建新任务
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
}
/// 获取任务状态
pub fn get_task_state(task_id: TaskId) -> Option<TaskState> {
// 从任务表中查询
TASKS.lock().get(&task_id).map(|t| t.state)
}
/// 获取当前任务 ID
pub 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; // 实时优先级
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()
}
}
// 任务 A 发送消息给任务 B
let 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 支持
Terminal window
# 启用任务调试输出
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
  • 解决:实现老化机制,逐渐提高等待任务的优先级

问题:死锁

  • 可能原因:循环等待资源
  • 解决:使用超时或打破循环依赖