標籤:
裝置驅動程式大概可分為兩種: 核心驅動程式及使用者空間驅動程式。
l 核心驅動程式
是核心空間實現的驅動程式,它使用核心資源,核心棧。它包括可載入的核心驅動模組。在這裡我想主要說說使用者空間驅動程式的編寫。
l 使用者空間驅動程式
就是指在使用者空間實現的驅動程式。可以認為,它跟普通的使用者程式沒有什麼兩樣,它使用使用者進程空間和棧。這裡說下,我不是討論接到串口,並口上什麼裝置!
大家不要以為在使用者空間寫驅動程式“不過癮!”。其實,作為裝置驅動程式,其主要做的事就是配置裝置寄存器(一家之言)。所以也不用把驅動程式看得那麼“神秘”。當然,有些裝置是不合適在使用者空間實現驅動的。個人認為,使用中斷的裝置不宜在使用者空間驅動,除此外,都有辦法在使用者空間來驅動。
在使用者空間實現驅動的一個好處就是,方便用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 = mmap(NULL,0x100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0xE0080000);
之後,你就可以使用reg_addr這個地址,在0x100大小空間範圍內配置你的PCI裝置了。
就這麼完了嗎?
在使用者空間實現的驅動程式,不用為裝置建立裝置檔案。當然,在多個進程使用時,要使用IPC機制來實現裝置臨界區的保護等。如果你真的感覺寫使用者空間的裝置驅動程式“沒什麼水平”,那你可以用它來調試好你的裝置(也是就知道怎麼設定寄存器)後,再花一點時間把它移到核心去,加上檔案系統介面,使用核心同步機制進行同步,再實現初始化函數,就可以變成核心驅動了。
這樣,你該滿意了吧!
本文來自:我愛研髮網(52RD.com) - R&D大本營
詳細出處:http://www.52rd.com/blog/Detail_RD.Blog_sbz_4327.html?WebShieldDRSessionVerify=boUBUf4rnKmnroDrFvFR
【轉】使用者空間編寫驅動程式