1. 程式人生 > >Linux用戶態驅動設計

Linux用戶態驅動設計

使用 同步 eve 顯卡 set等 download wikipedia usb 沒有

序言

設備驅動可以運行在內核態,也可以運行在用戶態,用戶態驅動的利弊網上有很多的討論,而且有些還上升到政治性上,這裏不再多做討論。不管用戶態驅動還是內核態驅動,他們都有各自的缺點。內核態驅動的問題是:系統調用開銷大;學習曲線陡峭;接口穩定性差;調試困難;bug致命;編程語言選擇受限;而用戶態驅動面臨的挑戰是:如何中斷處理;如何DMA;如何管理設備的依賴關系;無法使用內核服務等。對此,《User-Space Device Drivers in Linux: A First Look》 一文有較詳細描述。

可能是為了性能優化,或者為了故障隔離,或者為了逃避開源許可證的約束,不管是基於何種目的,linux已有多種用戶態驅動的實現,如UIO,VFIO、USB用戶態驅動等。它們在處理中斷、DMA、設備依賴管理等方面的設計方案和實現細節上各有千秋,這是《User-Space Device Drivers in Linux: A First Look》 沒有提到的,也是本文的重點。

UIO

技術分享圖片

UIO 框架導出sysfs和/dev/uioX 2套用戶態接口,用戶對設備節點/dev/uioX進行設備控制,mmap()接口用於映射設備寄存器空間,write()接口用於控制中斷關閉/打開,read()接口用於等待一個設備中斷。

因為對於設備中斷的應答必須在內核空間進行,所以在內核空間有一小部分代碼用來應答中斷和禁止中斷,其余的工作全部留給用戶空間處理。如果用戶空間要等待一個設備中斷,它只需要簡單的阻塞在對 /dev/uioX的read()操作上。 當設備產生中斷時,read()操作立即返回。UIO 也實現了poll()系統調用,你可以使用 select()來等待中斷的發生。select()有一個超時參數可以用來實現有限時間內等待中斷。

UIO的幾個特點:

  • 一個UIO設備最多支持5個mem和portio空間mmap映射。
  • UIO設備的中斷用戶態通信機制基於wait_queue實現。
  • 一個UIO設備只支持一個中斷號註冊,支持中斷共享。

總的來說,UIO框架適用於簡單設備的驅動,因為它不支持DMA,不能支持多個中斷線,缺乏邏輯設備抽象能力。

VFIO

技術分享圖片

上文提到,UIO不支持DMA,所以通過DMA傳輸大流量數據的IO設備,如網卡、顯卡等設備,無法使用UIO框架,VFIO做為UIO的升級版,主要就是解決了這個問題。通過用戶態配置IOMMU接口,可以將DMA地址空間映射限制在進程虛擬空間中。這對高性能驅動和虛擬化場景device passthrough尤其重要。

在VFIO框架中,有幾個核心概念或對象:IOMMU、/dev/vfio、container、iommu_group。

  • IOMMU是一個硬件單元,它可以把設備的IO地址映射成虛擬地址,為設備提供頁表映射,設備通過IOMMU將數據直接DMA寫到用戶空間。之所以不共用MMU單元,是為了保證和進程的頁表相互獨立,防止設備訪問進程的任意地址空間。所以VFIO的IOMMU功能保障了安全的非特權級別的用戶態設備驅動機制。
  • /dev/vfio是一個設備文件,作為一個IOMMU設備的用戶態呈現。
  • container是內核對象,表示一個IOMMU設備,是一個IOMMU設備的內核態呈現。所以在VFIO中,container是IOMMU操作的最小對象。
  • 在虛擬化場景下,一個物理網卡可能要虛擬成幾個虛擬網卡,或者說虛擬功能設備(VF),這幾個VF共用一個IOMMU,所以VFIO模型增加一個iommu_group的概念,用來表示共享同一個IOMMU的一組device。

VFIO的幾個特點:

  • VFIO設備支持多中斷號註冊。
  • 設備的中斷用戶態通信機制基於eventfd/irqfd實現。用戶通過/dev/vfio設備select/poll/epoll,從而實現中斷從內核態到用戶態的異步事件通知。
  • 支持對物理設備進行邏輯抽象。
  • 僅支持pci intx中斷共享,其他類型中斷不支持共享。
  • VFIO僅支持特定IOMMU設備,如x86與PowerPC平臺的PCI設備和ARM平臺的platform設備。

USB用戶態驅動

技術分享圖片

usbfs(USB file system)提供了一些在用戶空間下操作USB設備的函數接口和數據結構, 在開發用戶態驅動時, 可以直接利用這些函數接口來實現對 USB 設備的控制和數據傳輸。
libusb對usb file system提供的函數接口和數據結構進行了封裝, 可以有效減少程序中函數和數據結構使用不當造成的錯誤。Libusb 對 USB 設備的訪問提供了兩種機制, 同步訪問和異步訪問。
khubd是內核後臺線程,用來管理監視USB HUB的狀態, 一旦發生熱插拔就會喚醒這個線程, 進而添加或者移除設備,並發送netlink消息傳遞給用戶態空間。

USB 用戶態驅動框架的幾個特點:

  • 設備的中斷用戶態通信機制基於netlink實現。
  • USB設備以usbdevfs (後改名為usbfs)文件系統的形式(如/proc/bus/usb/BBB/DDD)對用戶態呈現。
  • 對usb的所有訪問通過usbfs ioctl實現,如control transfer, bulk transfer, reset等。
  • 僅支持USB設備

參考資料

Linux Kernel v4.4

User-Space Device Drivers in Linux: A First Look

User-Mode Driver Framework

VFIO Introduction

Linux iommu和vfio概念空間解構

Linux用戶態驅動設計