延迟 IO¶
延迟 IO 是一种延迟和重新利用 IO 的方法。 它使用主机内存作为缓冲区,并将 MMU 缺页作为何时执行设备 IO 的预触发器。 以下示例可能有助于解释一种这样的设置是如何工作的
用户空间应用程序(如 Xfbdev)mmap 帧缓冲
延迟 IO 和驱动程序设置故障和 page_mkwrite 处理程序
用户空间应用程序尝试写入 mmapped 的虚拟地址
我们得到缺页,并到达故障处理程序
故障处理程序找到并返回物理页面
我们得到 page_mkwrite,在这里我们将此页面添加到列表
调度一个工作队列任务,以便在延迟后运行
应用程序继续写入该页面,没有额外的成本。这是关键好处。
工作队列任务进入并 mkcleans 列表上的页面,然后完成与更新帧缓冲相关的任务。 这是与设备通信的真正工作。
应用程序尝试写入地址(现在已被 mkcleaned)
获取缺页,并且再次发生上述序列
从上面可以看出,一个好处是允许突发帧缓冲写入以最低成本发生。 然后,经过一段时间,当希望一切都平静下来时,我们去真正更新帧缓冲,这将是一个相对更昂贵的操作。
对于某些类型的非易失性高延迟显示器,所需的图像是最终图像,而不是中间阶段,这就是为什么不更新每次写入是可以接受的。
这种情况在其他场景中也可能有用。 Paul Mundt 提到了一种情况,即使用页面计数来决定是合并和发出 SG DMA 还是进行内存突发是有益的。
另一种情况可能是,如果有一个设备帧缓冲采用不寻常的格式,比如对角线移动 RGB,那么这可能是一种机制,允许应用程序假装拥有一个正常的帧缓冲,但根据触摸的页面列表,在垂直同步时重新整理设备帧缓冲。
如何使用它:(对于应用程序)¶
不需要更改。 像往常一样 mmap 帧缓冲并使用它即可。
如何使用它:(对于 fbdev 驱动程序)¶
以下示例可能有所帮助。
设置您的结构。例如
static struct fb_deferred_io hecubafb_defio = { .delay = HZ, .deferred_io = hecubafb_dpy_deferred_io, };
延迟是 page_mkwrite 触发器发生的时间与调用 deferred_io 回调的时间之间的最小延迟。 deferred_io 回调如下所述。
设置您的延迟 IO 回调。例如
static void hecubafb_dpy_deferred_io(struct fb_info *info, struct list_head *pagelist)
deferred_io 回调是您执行所有 IO 到显示设备的地方。 您收到 pagelist,它是延迟期间写入的页面列表。 您不得修改此列表。 此回调是从工作队列中调用的。
调用 init
info->fbdefio = &hecubafb_defio; fb_deferred_io_init(info);
调用 cleanup
fb_deferred_io_cleanup(info);