在linux系統中我們一直在說驅動,那么我們的驅動到底是什么東西呢?它又有什么作用呢?下面讓我們從最常見、最常用的字符設備驅動入手,掌握linux驅動開發的精髓。
一、驅動到底是什么?
1、概念:安裝操作系統之后,如果沒有外圍硬件的支持,用戶想操作的功能就實現不了,需要驅動工程師開發相應的驅動(硬件),有驅動代碼來操作硬件,完成相應的工作。
2、這里我們區分這樣兩個概念,大部分做過stm32開發的會說我以前直接操作寄存器也能實現硬件的驅動,那么與linux內核的驅動又有什么不同?我們都知道我們的linux內核具有五大功能:內存管理、進程管理、文件管理、網絡管理、設備管理。
1)、ARM裸機驅動:這段代碼是不需要依賴其他的代碼,由匯編語言或者c語言直接操作硬件寄存器。
2)、內核驅動:這一小段代碼必須依賴內核才能夠實現相應的功能,又C語言開發,這段代碼在寫時必須依賴一定框架。
二、驅動的種類
在Linux系統驅動程序中,我們要面臨各種硬件設備,所以我們的設備驅動有很多,比如: LED驅動,LCD驅動,觸摸屏驅動,攝像頭驅動,鼠標,鍵盤,u盤,硬盤,Flash,網卡,貓,路由器等等。
1、我們通常將這些驅動劃分為這幾類:
一)、字符設備驅動:字符設備驅動是以字節為單位,順序訪問的,字符設備是面向流的設備,也是我們最常見的一類設備驅動,常見的有鼠標、鍵盤、LED設備等。
二)、塊設備驅動:在訪問的時候是以扇區或者塊(512字節),訪問時是無序的,包括硬盤、U盤,磁盤和SD卡等。
三)、 網卡設備驅動:網絡適配器就是計算機的網絡連接設備,俗稱網卡,網卡通常有有線網卡和無線網卡,這就是硬件設備,而網卡驅動是配套的軟件,這個不怎么常見。
三、驅動的框架
我們通過驅動的一個層次架構模型可以清晰直觀的看到我們的驅動所處的位置有多重要。
四、字符設備驅動
1、那么對于剛接觸驅動的我們來說如何快速編寫一個驅動程序呢?
最好也是最快的方法是參考內核源代碼中的demo。例如現在,我想編寫我們第一個字符驅動程序,那么我們可以看看別人是怎么實現的,在內核driver目錄下找到led的驅動程序,參考別人是如何實現。還有就是廠家的參考demo。這是我們最快的學習方式。
2、下面我們要開始碼代碼了:
我們編寫一個字符設備文件,通常有這么幾步:
一)、定義結構體對象 struct cdev *cdev;
二)、為結構體分配空間
三)、對cdev結構體對象初始化
四)、分配設備號
五)、字符設備驅動的注冊(cdev和設備號關聯的過程)
我們首先寫出幾個函數模型,例如open、read、write。
然后我們要告訴內核有這兩個函數,通過file_operations 這個結構體來完成,通常定義在內核的include/linux/fs.h文件中,當應用程序操作設備文件時所調用的open、read、write等函數,最終會調用這個結構中所指定的對應函數:
然后通過一個函數告訴內核:
然后由我們的模塊入口函數指定的函數來調用上面這個函數,也就是我們的mycdev_init函數,里面完成了為cdev分配空間、設備號的申請、字符設備驅動的注冊等:
設備號:主設備號和次設備號(二者一起為設備號):一個字符設備或塊設備都有一個主設備號和一個次設備號。主設備號用來標識與設備文件相連的驅動程序,用來反映設備類型。次設備號被驅動程序用來辨別操作的是哪個設備,用來區分同類型的設備。
最后我們在模塊的出口函數進行資源的釋放。
下面這是我們編寫的Makefile
最后,我們通過手動創建設備文件:
sudo mknod /dev/first_drv(可以在任何路徑下) c 主設備號 次設備號
sudo chmod 777 /dev/first_drv
然后通過cat /proc/devices就可以查看我們添加的設備文件,