uio用戶態驅動



1.1為什么出現了UIO?
   硬件設備可以根據功能分為網絡設備,塊設備,字符設備,或者根據與CPU相連的方式分為PCI設備,USB設備等。它們被不同的內核子系統支持。這些標准的設備的驅動編寫較為容易而且容易維護。很容易加入主內核源碼樹。但是,又有很多設備難以划分到這些子系統中,比如I/O卡,現場總線接口或者定制的FPGA。通常這些非標准設備的驅動被實現為字符驅動。這些驅動使用了很多內核內部函數和宏。而這些內部函數和宏是變化的。這樣驅動的編寫者必須編寫一個完全的內核驅動,而且一直維護這些代碼。而且這些驅動進不了主內核源碼。於是就出現了用戶空間I/O框架(Userspace I/O framework)。

1.2 dpdk的uio使用

在基於kernel的IO模型中,所有的設備IO都要經過內核處理,在高並發的網絡數據包收發的情況下,大量硬件中斷會降低內核數據包處理能力,內核和用戶空間的數據拷貝也會造成大量的計算資源浪費。所以,作為高並發大流量網絡開發框架的DPDK,必須要找到一個能夠避免內核中斷爆炸和大量數據拷貝的方法,在用戶空間能夠直接和硬件進行交互。Linux的UIO就是這樣一個將硬件操作映射到用戶空間的kernel bypass方案。

下圖展示了UIO驅動的內核部分,用戶空間部分,和UIO框架以及內核的關系:

1.3 dpdk的網口綁定干了啥?

綁定操作:

./dpdk-devbind.py -b igb_uio 0000:00:07.0

既然是設備驅動程序一定會創建設備,/dev下查看:多出了uio0設備;

vm65:/dev # ll |grep uio
crw-------  1 root root    246,   0 Feb 18 07:41 uio0
vm65:/dev #

查看/sys/class/uio/uio:

vm65:/sys/class/uio/uio0 # ll
total 0
-r--r--r-- 1 root root 4096 Feb 18 06:42 dev
lrwxrwxrwx 1 root root    0 Feb 18 06:42 device -> ../../../0000:00:07.0
-r--r--r-- 1 root root 4096 Feb 18 06:42 event
drwxr-xr-x 4 root root    0 Feb 18 06:42 maps
-r--r--r-- 1 root root 4096 Feb 18 06:42 name
drwxr-xr-x 2 root root    0 Feb 18 06:42 power
lrwxrwxrwx 1 root root    0 Feb 18 06:42 subsystem -> ../../../../../class/uio
-rw-r--r-- 1 root root 4096 Feb 18 06:41 uevent
-r--r--r-- 1 root root 4096 Feb 18 06:42 version

同時,查看dmesg,多出了以下幾行信息:

<6>[171282.211083] igb_uio 0000:00:07.0: mapping 1K dma=0x123fb9b000 host=ffff88123fb9b000
<6>[171282.211088] igb_uio 0000:00:07.0: unmapping 1K dma=0x123fb9b000 host=ffff88123fb9b000

可以看到。綁定過程中的kernel part會通過uio_register_device 注冊對應的uio設備,獲取pcie的配置空間BAR信息包括addr、name、size、offset填充到map/map0中,這些在用戶態會將其讀出,並mmap至用戶態進程空間,這樣用戶態便可直接操作設備的內存空間。

除了內存管理,第二個任務,對於設備中斷的應答必須在內核空間進行。所以在內核空間有一小部分代碼用來應答和禁止中斷,中斷的其他任務由用戶態完成;

假設用戶空間要等待一個設備中斷,它僅僅須要簡單的堵塞在對 /dev/uioX的read()操作上。 當設備產生中斷時,read()操作馬上返回。

UIO 也實現了poll()系統調用。你能夠使用 select()來等待中斷的發生。select()有一個超時參數能夠用來實現有限時間內等待中斷。

 

1.4 用戶態驅動

常用的用戶態驅動開發有兩種方式可選:

1、打開/dev/mem 后,使用MMAP映射出芯片物理地址對應的虛擬地址,在用戶態訪問虛擬地址加偏移就能訪問到芯片的寄存器;

2、采用UIO方式,在內核態映射地址后,在用戶態通過打開/dev/uioxxx 方式,再使用MMAP映射一次,就可采用跟方式1 相同的方式訪問芯片reg或是memory;

這兩種方式各有優缺點:

方式1:優點是實現簡單,如果不需要用到中斷,可以不用管內核態的內容,關注用戶態代碼就好。缺點是代碼運行的進程要有root權限,不然無法訪問/dev/mem,如果要使用中斷還是會涉及到內核態的驅動;

方式2:優點是無需要root權限,中斷可以直接在用戶態獲取。缺點是必須要在內核態做初始化;即需要在內核態通過uio_register_device注冊對應的uio設備,這樣user space就可以通過/sys/class/uio/uioX/mapsX來訪問這個uio設備;

關鍵結構體&函數:

注冊uio設備前需要初始化對應的uio_info結構體:

struct uio_info {  
    struct uio_device   *uio_dev; // 在__uio_register_device中初始化 
    const char      *name; // 調用__uio_register_device之前必須初始化 
    const char      *version; //調用__uio_register_device之前必須初始化 
    struct uio_mem      mem[MAX_UIO_MAPS]; 
    struct uio_port     port[MAX_UIO_PORT_REGIONS]; 
    long            irq; //分配給uio設備的中斷號,調用__uio_register_device之前必須初始化 
    unsigned long       irq_flags;// 調用__uio_register_device之前必須初始化 
    void            *priv; // 
    irqreturn_t (*handler)(int irq, struct uio_info *dev_info); //uio_interrupt中調用,用於中斷處理 
                                                                                                   // 調用__uio_register_device之前必須初始化 
    int (*mmap)(struct uio_info *info, struct vm_area_struct *vma); //在uio_mmap中被調用, 
                                                                                                                // 執行設備打開特定操作 
    int (*open)(struct uio_info *info, struct inode *inode);//在uio_open中被調用,執行設備打開特定操作 
    int (*release)(struct uio_info *info, struct inode *inode);//在uio_device中被調用,執行設備打開特定操作 
    int (*irqcontrol)(struct uio_info *info, s32 irq_on);//在uio_write方法中被調用,執行用戶驅動的 
                                                                                       //特定操作。 
}; 

設備注冊函數:

#define uio_register_device(parent, info) __uio_register_device(THIS_MODULE, parent, info)
int __uio_register_device(struct module *owner,
              struct device *parent,
              struct uio_info *info)

用戶態驅動示例:

https://blog.csdn.net/ganggexiongqi/article/details/6751798

https://blog.csdn.net/ganggexiongqi/article/details/6748103


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM