一个基于 io_uring 的单线程异步磁盘 I/O 薄封装。
- Linux 内核(≥ 5.1,使用
IORING_SETUP_SQPOLL时需更高版本) - liburing
- CMake ≥ 3.10
- C++20 编译器(仅测试了GCC13)
mkdir build && cd build
cmake ..
makeread()/write()调用时,库认为期望执行对应动作,因此若一切顺利会直接提交,不对prep_count()进行计数,若提交失败则会prep_count()加1,并设置submit_error表示提交失败,而已准备的sqe可能随着任意一次提交从而提交。result_count()表示应拿多少个结果对象,如果强行获取更多的结果对象,则在调用结果对象的wait()时可能导致无法中止的阻塞,因此不建议通过get_result(true)强制获取(提供该接口是防止结果对象析构但没有消费而导致在结果队列永久滞留)。- 在
sqe准备后,若没有提交在大于当前cqe数量的结果对象调用wait()时可能导致无法中止的阻塞,而提交是否成功则在调用read()/write()/submit()后通过submit_err()检查。(此条已失效,在未提交成功前无法通过get_result()获取结果对象) queue_size()和result_count()语义相似但不同,前者表示提交和准备的数据有几条,使得他减少只有结果对象通过peek()/wait()消费后才会减去消费条目,后者表示还有几个结果对象应拿,只有通过get_result()才会减少计数。prep_count()返回已准备未提交的任务数量,当调用read()/write()/submit()提交后会根据成功提交的数量修改result_count()和prep_count()的计数。
- 在未通过
peek()/wait()前其绝大多数方法无效,只会返回默认值/空值。 - 读和写的情况下api语义不同需要注意。
is_valid在初始化时会检查map和ring是否有效,并以此设置is_valid。- 在调用
transfer_data()后is_valid会被设置为false,us_d内的buf会被设置为nullptr,这会使得大多数api失效,但不影响user_data(),size()和rw()。 - 若创建该对象的
async_io失效,则所有由这个async_io创建的结果对象全部失效。 - 调用
peek()/wait()所拿结果不保证和提交顺序一致,因此需要通过user_data()获取标记判断。 size()直接对应cqe->res因此某些情况可能为负数(虽然我认为这种情况应该不会存在,但以防万一在这里提一下)。
MIT