UIO

UIO

UIO(Userspace I/O)是運行在用戶空間的I/O技術。Linux系統中一般的驅動設備都是運行在內核空間,而在用戶空間用應用程序調用即可,而UIO則是將驅動的很少一部分運行在內核空間,而在用戶空間實現驅動的絕大多數功能,使用UIO可以避免設備的驅動程序需要隨著內核的更新而更新的問題。

定義


為什麼要把I/O放在用戶空間原因有二個
第一,硬體設備可以根據功能分為網路設備,塊設備,字元設備,或者根據與CPU相連的方式分為PCI設備,USB設備等。被不同的內核子系統支持。這些標準的設備的驅動編寫較為容易而且容易維護。很容易加入主內核源碼樹。但是,又有很多設備難以劃分到這些子系統中,比如I/O卡,現場匯流排介面或者定製的FPGA。通常這些非標準設備的驅動被實現為字元驅動。這些驅動使用了很多內核內部函數和宏。而這些內部函數和宏是變化的。這樣驅動的編寫者必須編寫一個完全的內核驅動,而且一直維護這些代碼。像這種設備如果把驅動放入Linux內核,不但增大了內核的負擔而且還很少使用,更沒有人願意免費的花費大量精力去維護這樣的驅動,使用UIO使驅動的開發可以利用所有的用戶空間的應用程序開發工具和庫,而且當系統內核發生變化時,只要更改UIO框架與其他內核程序交互的介面即可,不需要更改UIO框架下面的driver。
第二,內核驅動的開發必須使用C語言加上少量彙編代碼。uio可以使用C++,Java ...等高級語言極大的方便了開發。可以發現,有很多的卡的驅動在內核空間已經有實現,這樣,可以參考已經存在的代碼,極大的提高的開發的速度,和降低了開發成本。而且內核驅動的調試會比用戶空間程序調試複雜很多。經常遇到死機,涉及到多個子系統,棘手。放在用戶空間的話如果驅動程序死了,並不影響系統的正常運行並且方便了開發。

工作原理


通過UIO的運行原理圖可以看出,用戶空間下的驅動程序比運行在內核空間的驅動要多得多,UIO框架下運行在內核空間的驅動程序所做的工作很簡單,常做的只有兩個:分配和記錄設備需要的資源和註冊uio設備和必須在內核空間實現的小部分中斷應答函數,經過實踐表明後面的工作也是可以省略的!認為uio內核空間的程序所做的越少越好,在用戶空間能完成的就不需要放在內核空間做(比如說響應中斷),這樣假如內核有變化,uio框架中的驅動維護也是比較簡單的!對於用戶空間的驅動程序,還可以集成到某款應用軟體中,這樣也是可行的,上面已經說過了,因為使用uio的設備一般比較少見,所以可以作出這類的驅動也可以針對某款或者一類設備作出應用程序集成了驅動即可!

內核空間


UIO的少量運行在內核空間的驅動所做的工作有哪些。
(1)分配和記錄設備需要的資源和註冊uio設備
在設備的探測函數中:
- 使能PCI 設備
- 申請資源
- 讀取並記錄配置信息
- 註冊uio設備// uio_register_device()
// uio_8139d_pci_probe & uio_8139d_handler
(2)必須*在內核空間實現的小部分中斷應答函數
int32_t irq_count;
int fd = open("/dev/uio0", O_RDWR);
void * access = mmap(NULL, 4096,
// 寄存器的讀寫操作,可用過普通內存讀寫的方式完成
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);// [1]
while (read(fd, &irq_count, 4) == 4) {[2]
printf("Interrupt number %d\n", irq_count);
}