簡體   English   中英

數據采集​​設備的Linux驅動程序和API架構

[英]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行視頻數據,但是我們需要通知僅當整個視頻幀就緒時才可以使用)。 我們只需要將整個幀傳輸到用戶應用程序。

這是我們的首次嘗試:

  1. 我們的用戶端API允許用戶應用程序為“通道”注冊函數回調。
  2. 用戶端API具有“啟動”功能,可由用戶應用程序調用,該應用程序使用ioctl向內核驅動程序發送啟動消息。
  3. 在內核驅動程序中,接收到啟動消息后,我們啟動了一個內核線程,該線程連續監視“數據就緒”位向量,並在看到新數據時將其復制到驅動程序分配的(kmalloc)緩沖區中。 它會一直這樣做,直到收集到的數據大小達到“幀大小”為止。
  4. 此時,將自定義linux SIGNAL(類似於SIGINT,SIGHUP等)發送到運行驅動程序的進程。 我們的API會捕獲此信號,然后回調相應的用戶回調函數。
  5. 用戶回調函數調用API中的函數(transfer_data),該函數使用ioctl調用將用戶空間緩沖區地址發送到內核,內核通過將通道幀數據復制到用戶空間來完成數據傳輸。

上面的所有方法都可以正常工作,只是性能很差。 我們只能達到大約2MB /秒的傳輸速率。 我們需要完全重寫它,我們對任何建議或示例指針都持開放態度。

其他說明:

  • 不幸的是,我們無法更改硬件設備中的任何內容。 因此,我們必須輪詢“數據就緒”位並基於該位啟動DMA。

  • 有人建議參考Infiniband驅動程序作為參考,但是我們完全不了解該代碼。

您現在可能已經過去了,但如果沒有,這是我的2分。

  1. 很難相信您的卡在傳輸數據后不會產生中斷。 它具有DMA引擎,並且可以處理“描述符”,這大概是分散聚集列表的元素。 我假設它會產生PCIe“中斷”。 YMMV。
  2. 不要為現有的類似驅動程序而拖曳內核。 您可能會很幸運,但我懷疑不是。

您需要寫一個阻塞讀取,您將為其提供大的內存緩沖區。 讀取操作op(a)的驅動程序獲取用戶緩沖區的用戶頁面列表,並將其鎖定在內存中( get_user_pages ); (b)使用pci_map_sg創建一個分散列表; (c)遍歷列表( for_each_sg ); (d)對於每個條目,將相應的物理總線地址和數據長度寫入DMA控制器,就像我假設您所說的“描述符”一樣。

該卡現在具有一個描述符列表,這些描述符與大型用戶緩沖區的物理總線地址相對應。 當數據到達卡時,它將數據直接寫到用戶空間,用戶緩沖區中,而用戶級別的讀取仍被阻止。 完成描述符列表后,該卡必須能夠中斷,否則就沒用了。 驅動程序響應該中斷並取消阻止您的用戶級讀取。

就是這樣。 當然,這些細節是令人討厭的,並且文檔記錄很少,但這應該是基本的體系結構。 如果您確實沒有中斷,則可以在內核中設置一個計時器以輪詢傳輸是否完成,但是如果它確實是定制卡,則應該退還您的錢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM