异步执行与 SQPOLL 机制与实现详解
源码路径:
rk3588/kernel-6.1/io_uring/io-wq.c、sqpoll.c、tctx.c
文档目录:linuxDoc/io_uring/
目录
一、原理
当 issue() 不能在内核提交上下文立即完成(阻塞、-EAGAIN、显式 async),请求进入 io_wq,由 bound/unbound worker 执行。
SQPOLL 则用 内核线程 代替用户态反复 io_uring_enter 提交 SQ,适合 极高 IOPS 且可牺牲一核的场景。
二、io-wq
2.1 结构(io-wq.c)
| 概念 | 说明 |
|---|---|
struct io_wq |
每 ring 或 attach 的共享工作队列 |
struct io_worker |
内核线程,IO_WORKER_F_BOUND 区分绑核池 |
| hash bucket | 常规文件按 inode hash,减少锁竞争 |
IO_WQ_WORK_CANCEL |
退出或取消时标记 |
2.2 入队路径
io_queue_iowq(io_uring.c)根据 opdef:
hash_reg_file→ hash wqunbound_nonreg_file→ unbound wq(socket、pipe 等)
io_uring_register 可设置 IORING_REGISTER_IOWQ_AFF、IOWQ_MAX_WORKERS。
2.3 生命周期
- worker 空闲 5*HZ 超时回收(
WORKER_IDLE_TIMEOUT) - 任务退出:
io_uring_cancel_generic取消 inflight
三、SQPOLL
3.1 struct io_sq_data
多个 ring 可共享 sqpoll 线程(IORING_SETUP_ATTACH_WQ 相关路径)。
| API | 作用 |
|---|---|
io_sq_thread_park / unpark |
注册变更时停线程 |
io_sq_thread_stop |
销毁 |
3.2 io_uring_enter 行为
若 IORING_SETUP_SQPOLL:
- 用户 通常只 wakeup(
IORING_ENTER_SQ_WAKEUP)或 SQ_WAIT - 实际
io_submit_sqes在 sqpoll 线程 中执行
IORING_SQ_NEED_WAKEUP:应用更新 tail 后需唤醒(memory barrier 后检查)。
四、tctx 每任务上下文
struct io_uring_task(current->io_uring):
| 成员 | 作用 |
|---|---|
io_wq |
任务级工作队列 attach |
registered_rings[] |
IORING_REGISTER_RING_FDS,加速 enter |
cached_refs |
批量提交引用计数缓存 |
task_list / task_work |
DEFER_TASKRUN 本地工作 |
io_uring_alloc_task_context:首次使用 ring 时分配。
五、RK3588
- SQPOLL + SQ_AFF:建议绑 大核(Cortex-A76/A77),避免小核导致抖动
- IOWQ 线程数:默认随 CPU;嵌入式可限制以免与 媒体线程 争用
- 无 Rockchip 专用 sqpoll 逻辑
附录
| 文件 | 关键符号 |
|---|---|
io-wq.c |
io_wq_submit_work(入口在 io_uring.c 包装) |
sqpoll.c |
sqpoll 主循环 |
tctx.c |
ring fd 注册 |
相关:02 提交完成
正在加载留言…