編寫Linux用戶空間驅動程序

設備驅動程序大概可分爲兩種:

內核驅動程序及用戶空間驅動程序。

內核驅動程序

是內核空間實現的驅動程序,它使用內核資源,內核棧。它包括可加載的內核驅動模塊。在這裏我想主要說說用戶空間驅動程序的編寫。

用戶空間驅動程序

就是指在用戶空間實現的驅動程序。可以認爲,它跟普通的用戶程序沒有什麼兩樣,它使用用戶進程空間和棧。這裏說下,我不是討論接到串口,並口上什麼設備!

大家不要以爲在用戶空間寫驅動程序不過癮!其實,作爲設備驅動程序,其主要做的事就是配置設備寄存器(一家之言)。所以也不用把驅動程序看得那麼神祕。當然,有些設備是不合適在用戶空間實現驅動的。個人認爲,使用中斷的設備不宜在用戶空間驅動,除此外,都有辦法在用戶空間來驅動。

在用戶空間實現驅動的一個好處就是,方便用GDB調試。

怎麼寫

上面說到,驅動程序主要做的事情就是配置設備寄存器。那麼,只要在用戶空間,我能獲得到寄存器地址(或是映像地址)那就可以驅動這個設備了。

PCI設備爲例,假設你的PCI設備主芯片的配置寄存器在PCI配置頭的0x14位置:

首先:通過/proc文件系統的pci文件,及/proc/bus/pci目錄下的文件,可以獲取到你的設備PCI配置頭的信息,當然,也可以讀出0x14偏移的值。假設其值爲0xE0080000;這個就是你的PCI設備主芯片的配置寄存器的物理地址。在有MMU的處理器裏,直接使用這個地址是不允許的。我們都知道,在用戶進程空間尋址一個物理地址,首先要把這個物理地址映射到進程空間內。

怎麼映射呢?

我們知道,在Linux/dev目錄下,有一個mem的設備。我們簡單認爲它就是管理0x00000000-0xFFFFFFFF(32位處理器)物理地址的一個設備(不單指物理內存,它的空間也含蓋了PCI地址空間)。將PCI配置寄存器空間映射到進程空間的邏輯如下:

 

fd = open("/dev/mem",O_RDWR);

reg_addr = mmapNULL,0x100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0xE0080000);

 

之後,你就可以使用reg_addr這個地址,在0x100大小空間範圍內配置你的PCI設備了。

就這麼完了嗎

在用戶空間實現的驅動程序,不用爲設備建立設備文件。當然,在多個進程使用時,要使用IPC機制來實現設備臨界區的保護等。如果你真的感覺寫用戶空間的設備驅動程序沒什麼水平,那你可以用它來調試好你的設備(也是就知道怎麼設置寄存器)後,再花一點時間把它移到內核去,加上文件系統接口,使用內核同步機制進行同步,再實現初始化函數,就可以變成內核驅動了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章