延迟 IO

延迟 IO 是一种延迟和重新利用 IO 的方法。 它使用主机内存作为缓冲区,并将 MMU 缺页作为何时执行设备 IO 的预触发器。 以下示例可能有助于解释一种这样的设置是如何工作的

  • 用户空间应用程序(如 Xfbdev)mmap 帧缓冲

  • 延迟 IO 和驱动程序设置故障和 page_mkwrite 处理程序

  • 用户空间应用程序尝试写入 mmapped 的虚拟地址

  • 我们得到缺页,并到达故障处理程序

  • 故障处理程序找到并返回物理页面

  • 我们得到 page_mkwrite,在这里我们将此页面添加到列表

  • 调度一个工作队列任务,以便在延迟后运行

  • 应用程序继续写入该页面,没有额外的成本。这是关键好处。

  • 工作队列任务进入并 mkcleans 列表上的页面,然后完成与更新帧缓冲相关的任务。 这是与设备通信的真正工作。

  • 应用程序尝试写入地址(现在已被 mkcleaned)

  • 获取缺页,并且再次发生上述序列

从上面可以看出,一个好处是允许突发帧缓冲写入以最低成本发生。 然后,经过一段时间,当希望一切都平静下来时,我们去真正更新帧缓冲,这将是一个相对更昂贵的操作。

对于某些类型的非易失性高延迟显示器,所需的图像是最终图像,而不是中间阶段,这就是为什么不更新每次写入是可以接受的。

这种情况在其他场景中也可能有用。 Paul Mundt 提到了一种情况,即使用页面计数来决定是合并和发出 SG DMA 还是进行内存突发是有益的。

另一种情况可能是,如果有一个设备帧缓冲采用不寻常的格式,比如对角线移动 RGB,那么这可能是一种机制,允许应用程序假装拥有一个正常的帧缓冲,但根据触摸的页面列表,在垂直同步时重新整理设备帧缓冲。

如何使用它:(对于应用程序)

不需要更改。 像往常一样 mmap 帧缓冲并使用它即可。

如何使用它:(对于 fbdev 驱动程序)

以下示例可能有所帮助。

  1. 设置您的结构。例如

    static struct fb_deferred_io hecubafb_defio = {
            .delay          = HZ,
            .deferred_io    = hecubafb_dpy_deferred_io,
    };
    

延迟是 page_mkwrite 触发器发生的时间与调用 deferred_io 回调的时间之间的最小延迟。 deferred_io 回调如下所述。

  1. 设置您的延迟 IO 回调。例如

    static void hecubafb_dpy_deferred_io(struct fb_info *info,
                                         struct list_head *pagelist)
    

deferred_io 回调是您执行所有 IO 到显示设备的地方。 您收到 pagelist,它是延迟期间写入的页面列表。 您不得修改此列表。 此回调是从工作队列中调用的。

  1. 调用 init

    info->fbdefio = &hecubafb_defio;
    fb_deferred_io_init(info);
    
  2. 调用 cleanup

    fb_deferred_io_cleanup(info);