DragonOS/docs/kernel/interrupt/workqueue.md

141 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DragonOS Workqueue 机制设计文档
## 1. 概述
工作队列Workqueue是 DragonOS 内核中的一种"下半部"Bottom Half机制用于将任务推迟到**进程上下文**中执行。与 Softirq 和 Tasklet 不同,工作队列的处理函数运行在内核线程中,因此允许执行以下操作:
- 睡眠(阻塞等待资源)
- 获取互斥锁Mutex或信号量
- 执行 I/O 操作
- 分配内存(可能导致阻塞)
本机制的设计参考了 Linux 内核的工作队列实现,并针对 DragonOS 的 Rust 架构进行了适配。
## 2. 核心架构
### 2.1 核心组件
Workqueue 机制主要由以下三个组件构成:
1. **Work工作项**
- 定义了需要延迟执行的具体任务。
- 在 Rust 实现中本质上是一个封装了闭包Closure或函数指针的结构体。
- 通过 `Arc` 进行引用计数管理,支持跨线程共享。
2. **WorkQueue工作队列**
- 负责管理待处理的工作项Pending Works
- 维护一个或多个关联的**工作线程Worker Thread**。
- 内部包含一个 FIFO 队列和一个 `WaitQueue`(用于线程同步)。
3. **Worker Thread工作线程**
- 一个专门的内核线程,循环从 WorkQueue 中取出任务并执行。
- 当队列为空时,线程进入睡眠状态(通过 `WaitQueue` 挂起)。
- 当有新任务入队时,线程被唤醒。
### 2.2 数据流图
```mermaid
graph TD
User[调用者 (Driver/Interrupt)] -->|schedule_work()| WQ[WorkQueue]
WQ -->|enqueue| Queue[待处理队列]
WQ -->|wakeup| Worker[Worker Thread]
subgraph Worker Thread Loop
Check{队列为空?} -->|Yes| Sleep[睡眠等待]
Check -->|No| Dequeue[取出 Work]
Dequeue --> Run[执行 Work.func()]
Run --> Check
end
Sleep -.->|被唤醒| Check
```
## 3. 详细设计
### 3.1 数据结构设计
#### Work
`Work` 结构体封装了具体的任务逻辑。使用 `Box<dyn Fn() + Send + Sync>` 来存储闭包,确保其可以在线程间安全传递和执行。
```rust
pub struct Work {
func: Box<dyn Fn() + Send + Sync>,
}
```
#### WorkQueue
`WorkQueue` 是核心管理结构。它包含:
- `queue`: 一个受自旋锁SpinLock保护的双端队列存储 `Arc<Work>`
- `wait_queue`: 用于工作线程的同步等待。
- `worker`: 指向关联内核线程 PCB 的引用。
```rust
pub struct WorkQueue {
queue: SpinLock<VecDeque<Arc<Work>>>,
wait_queue: Arc<WaitQueue>,
worker: SpinLock<Option<Arc<ProcessControlBlock>>>,
}
```
### 3.2 运行机制
1. **初始化**
- 调用 `WorkQueue::new(name)` 创建一个新的工作队列。
- 该操作会自动启动一个名为 `name` 的内核线程。
2. **任务调度**
- 调用者使用 `Work::new(closure)` 创建工作项。
- 调用 `wq.enqueue(work)` 将任务加入队列。
- `enqueue` 操作会将任务推入队列尾部,并调用 `wait_queue.wakeup()` 唤醒工作线程。
3. **任务执行**
- 工作线程运行 `worker_loop` 函数。
- 循环检查队列状态:
- 若队列非空:取出队首任务,调用 `work.run()` 执行。
- 若队列为空:在 `wait_queue` 上调用 `wait_event_interruptible` 进入睡眠,等待被唤醒。
### 3.3 系统全局队列 (`SYSTEM_WQ`)
为了简化常见场景的使用,系统提供了一个全局默认工作队列 `SYSTEM_WQ`
- 大多数简单的后台任务可以直接提交到该队列,无需创建专用的 WorkQueue。
- 通过 `schedule_work(work)` 接口直接调度。
## 4. 接口说明
### 4.1 创建任务
```rust
let work = Work::new(|| {
log::info!("This is running in a workqueue!");
// 可以安全地睡眠或加锁
});
```
### 4.2 调度任务
```rust
// 调度到系统默认队列
schedule_work(work);
// 或者调度到自定义队列
let my_wq = WorkQueue::new("my_driver_wq");
my_wq.enqueue(work);
```
## 5. 与 Linux 的异同
- **相同点**
- 都是基于内核线程的延迟执行机制。
- 都支持睡眠和阻塞操作。
- 都提供了系统默认的全局队列。
- **不同点**
- **并发模型**DragonOS 当前实现采用"单线程单队列"模型(每个 WorkQueue 对应一个内核线程。Linux 采用复杂的 Worker Pool 模型支持动态扩缩容和并发管理CM
- **Per-CPU**DragonOS 当前未实现 Per-CPU 的 WorkQueue所有任务在同一个线程队列中处理。
- **API 风格**DragonOS 利用 Rust 的闭包特性,使得任务定义更加灵活简洁,不需要像 Linux 那样嵌入 `work_struct` 到自定义结构体中(尽管也支持类似模式)。
## 6. 未来演进
1. **并发管理**:引入 Worker Pool 机制,允许多个 Worker 消费同一个队列,提高并发度。
2. **Per-CPU 队列**:实现 Per-CPU 的 WorkQueue减少锁竞争提高缓存局部性。
3. **延迟工作Delayed Work**:集成定时器机制,支持 `schedule_delayed_work`,允许任务在指定延迟后执行。