我的理解(可能是错误的)是操作可以处于 io_uring 中三种可能状态之一:
想象一个应用程序请求数百万个 IO 操作,并且有两个线程,以及一个具有 32 个提交队列条目槽的 io_uring 实例。
一个线程负责保持提交队列填满:当应用程序启动时,该线程会用 32 个条目填充提交队列。然后,当提交队列已满时,它会阻塞。一旦提交队列变得“未满”,它就会提交另一个 SQE。
另一个线程获取完成队列事件。
此应用程序可能会溢出完成队列吗?
“使用 io_uring 实现高效 IO”PDF 建议 - 是的 - 这个应用程序将溢出完成队列:
通常申请会要求提供给定尺寸的戒指,并且 假设该大小直接对应于应用程序可以在 核心。然而,由于 sqe 的生命周期只是它实际提交的生命周期,应用程序是否必须跟踪正在进行的操作数量?或者如果CQ已满,是否有更简单的方法可以暂停向SQ的提交?应用程序有可能 驱动比 SQ 环大小指示的更高的待处理请求计数。应用程序必须注意不要这样做, 否则可能会导致 CQ 环溢出。缺省情况下,CQ环的大小是SQ环的2倍。这允许 在管理这方面应用了一定的灵活性,但并没有完全消除这样做的需要。如果 应用程序确实违反了此限制,它将作为 CQ 环中的溢出条件进行跟踪。
设置
IORING_SETUP_CQ_NODROP
标志将 -引用 Jen Axboe:
稍微改变一下行为 对于CQ环溢出。首先,它不会溢出环,它 只是存储我们无法放入的积压完成工作 CQ环。为了防止积压无限期地增长,如果 backlog非空,我们对IO提交施加反压。任何 尝试提交具有非空积压的新 IO 将得到 -EBUSY 从内核返回。这是向应用程序发出的一个信号: 积压的 CQ 事件,并且必须在允许之前获取这些事件 提交更多 IO。因此,调用
io_uring_enter()
将返回
-EBUSY
。但是,如果我们使用内核线程来轮询提交队列(使用
IORING_SETUP_SQPOLL
)呢?在这种情况下,我们不会调用
io_uring_enter()
,因此我们永远不会看到
-EBUSY
错误。我认为这里的解决方案是在尝试向提交队列提交任何内容之前调用 liburing 的 ?