Magic Buffers and io_uring Registered Buffers
摘要
文章介绍了一种 mmap 技巧:把同一段底层内存映射到两个在虚拟地址空间中相邻的区域,使得写越过第一个区域尾部时,会自然落到第二个映射区,从而形成类似环形缓冲的效果(作者称其为 Magic Buffer / Magic Ring Buffer)。作者进一步测试这种虚拟内存结构是否能与 io_uring 的 registered buffers 机制兼容,结论是可以正常工作。 他实现了一个小测试程序:构造 Magic Buffer(基于 MgCircularBuffer 实现),将该 buffer 的“双重映射范围”注册到内核作为 io_uring 的固定缓冲区,然后让一条 KDB IPC 消息跨越缓冲区“接缝”写入,最后通过 io_uring 的 fixed write 将消息发送到多个已连接的 KDB 实例。测试结果表明整个链路在这种内存布局下依然按预期运行。
荐读理由
在设计高性能 IO 或服务端缓冲结构时,可以利用同一底层内存被 mmap 成首尾相接的“双映射”方式构造连续逻辑空间,并与 io_uring 的 registered buffers 组合,将跨边界写入与固定缓冲发送统一在同一套零拷贝路径中处理。
原文
There’s a really cool little mmap gadget that maps the same underlying memory region into two contiguous virtual memory address ranges. When you write past the end of the first mapped region, the remaining bytes end up in the second mapped region (and at the start of the first one). Fabien Giesen calls this a “Magic Ring Buffer”, which is good enough for me.
I wondered whether the virtual memory contortions would survive contact with IO Uring’s registered buffers. It turns out (spoiler alert) that they do, and it’s virtual memory all the way down.
I wrote a little test application, and have published it on my Github with some more comments here.
Essentially, what the app does is:
Constructs a Magic Buffer (using my
MgCircularBufferimplementation here, I know … it’s not circular)Uses
io_uring_register_buffersto register the buffer’s “double extent” with the kernelWrites a kdb IPC message across the “seam” in the magic buffer
Uses
io_uring_prep_write_fixedto send the message to a couple of connected KDB instances
It works as expected.
这条对你有帮助吗?