LWN:io_uring可以自动选择使用哪个buffer了!

关注了就能看到更多这么棒的文章哦~

Automatic buffer selection for io_uring

By Jonathan Corbet
March 20, 2020

原文来自:https://lwn.net/Articles/815491/

主译:DeepL(https://www.deepl.com/)

io_uring子系统在过去的一年里重新定义了Linux系统中异步I/O使用方式。随着这个子系统的能力和用户的同步增长,在所支持的types of operations上开始碰到一些限制。这推动了io_uring操作的编程方式发生新的变化。一个例子是在3月初的时候LWN介绍的在多个operation之间传递文件描述符的机制(LWN:更快读出文件内容的两种新方法!)。另一个例子就是如何针对目标operation来选择I/O buffer。

正如 io_uring 开发者 Jens Axboe 在这组新patch set中所描述的那样,对于那些通常需要处理许多文件描述符的程序来说,传统模式是调用 poll()来找出哪些描述符已经准备好进行 I/O,然后逐个调用来实际执行 I/O。在这种模式下,我们可以使用io_uring,但这有违整个功能的一个核心目标:尽可能避免系统调用。如果用上io_uring的话,就是针对每个文件描述符都把这个异步操作加入队列,然后在某个操作完成的时候,来处理一下返回事件即可。

这种方式确实可以减少系统调用——甚至在request ring非常繁忙的情况下,可以将系统调用次数减少到接近零。但它也有缺点,需要为每个队列中的operation都分配一个单独的I/O缓冲区,尽管其中许多operation可能在未来一段时间内肯定无法执行到的。poll()方式则刚好与之相反,它允许应用程序将缓冲区分配推迟到实际需要缓冲区时。失去这种灵活性的话,对于那些需要等待许多operation的应用程序来说,会导致内存使用量大大增加。

这里需要某种机制,允许在operation在ring中排队之后再分配缓冲区。解决方案非常显而易见:在系统中增加一个可以调用BPF program的hook点,从而在某个operation要真正进行的时刻来在内核中管理分配缓冲区。我们应该完全不需要考虑其他解决方案了吧?不过,Axboe说,"I had a hard time imagining how life times of the buffer could be managed through [BPF]",所以这个想法被抛弃了。

幸好还有一个想法作为备选:让应用程序向io_uring提供一个或多个buffer pool,然后当需要缓冲区时,io_uring会从其中的一个buffer pool中选择一个buffer。这就是Axboe最终实现方案。

为了使用这种机制,应用程序开始时,需要先在队列中插入若干个IO_ING_OP_PROVIDE_BUFFERS操作,从而告诉内核我这边提供了哪些I/O buffers。每个操作都提供了缓冲区的基本地址、缓冲区的计数、缓冲区的大小(一次operation中所有缓冲区都是一样大的)、base buffer ID和group ID。如果请求中包含了一个以上的缓冲区,buffer ID将针对每个buffer来递增。虽然没有明确规定说某个buffer group中的所有buffer大小必须相同,不过看来设计者是希望这么使用的。

接下来在队列中插入后续operation的时候就可以不提供buffer,而是使用一个特殊值IOSQE_BUFFER_SELECT。队列中每个entry中新增的buf_group字段应设置为目标buffer group ID。当一个operation具备继续执行的条件时,内核将从指定buffer group中获取一个缓冲区来使用。在选择时并不考虑缓冲区的大小,因此如果缓冲区太小的话operation将无法正常完成。被使用的buffer ID会在operation完成时跟completion status一起返回。

如果所申请的buffer group没法提供buffer,那么operation会报出ENOBUFS错误并退出。一旦某个buffer被某个operation申请去了,内核将不会再使用它,直到有个IORING_OP_PROVIDE_BUFFERS调用来把它送回来。

当前的patch set只给一部分operation增加了buffer选择的能力。也就是read()、readv()、recv()和recvmsg()。早期版本的时候还支持write(),不过LWN编辑得坦诚,当时我看了代码也没看懂是怎么实现的。后来write()的操作在第三版中就移除了。

这项工作还没能合入linux-next中,不过现在离打开5.7 merge window还有不少时间。因此很可能这个buffer-selection功能可以被包含在下个开发周期之中。这一定会增加io_uring操作的灵活性,并且不需要BPF hook。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值