[英]Linux Driver and API architecture for a data acquisition device
我們正在嘗試為自定義數據獲取設備編寫驅動程序/ API,該設備可捕獲多個數據“通道”。 為了便於討論,我們假設這是一個多通道視頻捕獲設備。 該設備通過8xPCIe Gen-1鏈路連接到系統,其理論吞吐量為16Gbps。 我們的實際數據速率約為2.8Gbps(〜350MB /秒)。
由於數據速率要求,我們認為我們必須對驅動程序/ API體系結構保持謹慎。 我們已經實現了基於描述符的DMA機制和相關的驅動程序。 例如,我們可以從設備啟動一個256KB的DMA事務,該事務成功完成。 但是,在此實現中,我們僅在內核驅動程序中捕獲數據,然后將其刪除,並且根本不將數據流傳輸到用戶空間。 本質上,這只是一個小的DMA測試實現。
我們認為我們必須將問題分為三個部分:1.內核驅動程序2.用戶空間API 3.用戶代碼
采集設備在PCIe地址空間中有一個寄存器,該寄存器指示是否有數據要從該設備的任何通道讀取。 因此,我們的內核驅動程序必須輪詢此位向量。 當內核驅動程序看到該位置1時,它將啟動DMA事務。 但是,在准備好整個數據塊之前,用戶應用程序不需要了解所有這些DMA事務和數據(例如,假定該設備每個事務為我們提供16行視頻數據,但是我們需要通知僅當整個視頻幀就緒時才可以使用)。 我們只需要將整個幀傳輸到用戶應用程序。
這是我們的首次嘗試:
上面的所有方法都可以正常工作,只是性能很差。 我們只能達到大約2MB /秒的傳輸速率。 我們需要完全重寫它,我們對任何建議或示例指針都持開放態度。
其他說明:
不幸的是,我們無法更改硬件設備中的任何內容。 因此,我們必須輪詢“數據就緒”位並基於該位啟動DMA。
有人建議參考Infiniband驅動程序作為參考,但是我們完全不了解該代碼。
您現在可能已經過去了,但如果沒有,這是我的2分。
您需要寫一個阻塞讀取,您將為其提供大的內存緩沖區。 讀取操作op(a)的驅動程序獲取用戶緩沖區的用戶頁面列表,並將其鎖定在內存中( get_user_pages
); (b)使用pci_map_sg
創建一個分散列表; (c)遍歷列表( for_each_sg
); (d)對於每個條目,將相應的物理總線地址和數據長度寫入DMA控制器,就像我假設您所說的“描述符”一樣。
該卡現在具有一個描述符列表,這些描述符與大型用戶緩沖區的物理總線地址相對應。 當數據到達卡時,它將數據直接寫到用戶空間,用戶緩沖區中,而用戶級別的讀取仍被阻止。 完成描述符列表后,該卡必須能夠中斷,否則就沒用了。 驅動程序響應該中斷並取消阻止您的用戶級讀取。
就是這樣。 當然,這些細節是令人討厭的,並且文檔記錄很少,但這應該是基本的體系結構。 如果您確實沒有中斷,則可以在內核中設置一個計時器以輪詢傳輸是否完成,但是如果它確實是定制卡,則應該退還您的錢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.