提交与完成路径机制与实现详解
源码路径:
rk3588/kernel-6.1/io_uring/io_uring.c、io_uring.h
文档目录:linuxDoc/io_uring/
目录
一、原理
提交路径把用户 SQE 转为 io_kiocb 并尽量 同步 issue;若返回 -EAGAIN 或 op 需要阻塞,则转入 io-wq 或 poll。完成路径将结果写入 CQ,必要时 batch flush 并 signal eventfd。
二、提交流程
2.1 io_submit_sqes
1 | int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr) |
- 持有
ctx->uring_lock(非 SQPOLL 的 enter 路径) io_get_sqe:校验 index、从sq_array取 SQE 指针io_submit_sqe:parse opcode、prep、链式/延迟/直发io_queue_sqeIORING_SETUP_SUBMIT_ALL:单个 SQE 失败仍继续提交
2.2 io_issue_sqe
1 | ret = def->issue(req, issue_flags); |
io_assign_file:普通 fdget 或 固定文件表IOU_ISSUE_SKIP_COMPLETE:异步进行中(如-EIOCBQUEUED)IOU_OK:同步完成,立即 post CQE
三、issue 与完成
3.1 完成写入
io_get_cqe:使用cqe_cached快速路径,耗尽则__io_get_cqe__io_commit_cqring_flush:更新cq.tail、memory barrierio_req_complete_post:链式触发、REQ_F_LINK失败传播
3.2 io_wq_submit_work
worker 中再次 io_issue_sqe,-EAGAIN 时可 arm poll 或 iopoll 重试(见 io_uring.c ~1773)。
3.3 IOPOLL
io_do_iopoll / io_iopoll_check:对支持 iopoll 的块请求轮询 ->iopoll_completed。
四、链接与批量
| SQE 标志 | 行为 |
|---|---|
IOSQE_IO_LINK |
顺序执行,前一失败则跳过后续 |
IOSQE_IO_HARDLINK |
更强链接语义 |
IOSQE_BUFFER_SELECT |
由内核从 provide buffer 选缓冲区(kbuf.c) |
io_submit_state 可对同一批请求 plug 块层(opdef.plug)。
五、overflow 与 task_work
- CQ 满:
io_req_cqe_overflow→ overflow 链表,cq_overflow计数 IORING_SETUP_DEFER_TASKRUN:完成工作进work_llist,io_run_local_work处理tctx_task_work:与task_work集成,保证在进程上下文完成 UAPI 可见操作
六、调试
initcall_debug不适用;使用trace_io_uring_complete、trace_io_uring_submit- 观察
sq_dropped:用户 SQ 索引无效
附录
| 返回值 | 含义 |
|---|---|
IOU_OK (0) |
同步完成 |
IOU_ISSUE_SKIP_COMPLETE |
已排队,勿重复 complete |
-EIOCBQUEUED |
同 SKIP_COMPLETE 语义(历史) |
正在加载留言…