延遲 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);