驅動概述
驅動用在哪裏?非標準類設備的編寫和標準類設備的驅動移植。
驅動其實是隨着linux內核相伴而生的。某段代碼可以控制咱們的硬件去工做,去動,這段代碼就稱爲咱們的驅動代碼。
技術只是一種手段,一種技巧,咱們應該利用技術去搞出產品。
5.1.1_2.什麼是驅動1_2
5.1.1.一、理解驅動的概念
(1)驅動一詞的字面意思
(2)物理上的驅動
(3)硬件中的驅動
(4)linux內核驅動。軟件層面的驅動廣義上就是指:這一段代碼操做了硬件去動,因此這一段代碼就叫硬件的驅動程序。(本質上是電力提供了動力,而驅動程序提供了操做邏輯方法)
狹義上驅動程序就是專指操做系統中用來操控硬件的邏輯方法部分代碼。
5.1.1.二、linux體系架構(下層用來實現上層,上層來調用下層)
(1)分層思想
(2)驅動的上面是系統調用API(驅動對上對系統調用API負責,API又對應用程序負責)
(3)驅動的下面是硬件(驅動對下管理硬件,本質上驅動是操控硬件寄存器的)
(4)驅動本身自己也是分層的()
5.1.3.模塊化設計
5.1.3.一、微內核和宏內核(操做系統設計的兩種思路)
(1)宏內核(又稱爲單內核):將內核從總體上做爲一個大過程實現(能夠理解爲整個內核就是一個裸機程序,整個內核是一塊兒來寫的),並同時運行在一個單獨的地址空間。全部的內核服務都在一個地址空間運行,【相互之間直接調用函數】,簡單高效,架構設計比較簡單。(耦合性比較高,可是有缺陷,一個不工做其餘也不能工做了)
(2)微內核:功能被劃分紅獨立的過程,過程間經過【IPC進程間通訊】進行通訊。模塊化程度高(耦合性比較低),一個服務失效不會影響另一個服務。典型如windows
(3)linux:本質上是宏內核,可是又吸取了微內核的模塊化特性,體如今2個層面
5.1.3.二、靜態模塊化:在編譯時(源代碼級別)實現可裁剪,特徵是想要功能裁剪改變必須從新編譯整個內核,比較複雜。獲得一個新的zImage來代替舊的zImage,而後再去燒錄才能起效果。【相似於安卓的卡刷】
這種方式來講這個驅動模塊就屬於內核。
5.1.3.三、動態模塊化:zImage能夠不從新編譯燒錄,甚至能夠不關機重啓就實現模塊的安裝和卸載。【相似於安卓的線刷】這種方式其實嚴格來講這個驅動模塊不屬於內核,它能夠在須要的時候進行使用,在不須要的時候能夠卸載。
5.1.4.linux設備驅動分類
5.1.4.一、驅動分類
(1)分3類:字符設備驅動、塊設備驅動、網絡設備驅動
(2)分類原則:設備自己讀寫操做的特徵差別(硬件來決定軟件怎麼寫,由於硬件進行了分類,因此操控硬件的軟件程序(即驅動程序)也進行了分類)
就好像鞋子和腳的關係(鞋子的製做要適應腳的形狀等特性)
5.1.4.二、三類驅動程序詳細對比分析
(1)字符設備,準確的說應該叫「字節設備」,也就是這個設備的讀寫是:軟件操做設備時是以【字節】爲單位進行的。典型的如LCD、串口、LED、蜂鳴器、觸摸屏······
(2)塊設備,塊設備是相對於字符設備定義的,塊設備被軟件操做時是以【塊(多個字節構成的一個單位)】爲單位的。設備的塊大小是設備自己設計時定義好的,是硬件決定好的,軟件是不能去更改的,不一樣設備的塊大小能夠不同,但總的來講塊的大小是固定的。常見的塊設備都是存儲類設備,如:硬盤、NandFlash、iNand、SD···· (塊設備不能按照字節方式去讀)塊設備主要就是爲存儲設備而生的。
塊設備要把整個塊讀到內存中,而後在內存中定位到某個字節中進行讀寫。
(3)網絡設備,網絡設備是【專爲網卡設計】的驅動模型,linux中網絡設備驅動主要目的是爲了支持API中socket相關的那些函數工做。【由於網絡通訊有一套專用的接口和體系,因此單獨放在一類中。】
5.1.4.三、爲何字符設備驅動最重要
(1)常見大量設備都屬於字符設備
(2)舉例說明【非標準類型】字符設備驅動
標準類設備是指比較廣泛的設備,而非標準類型設備是爲某種專有功能,特定製做的設備。
5.1.5.驅動程序的安全性要求(寫驅動就至關於在寫內核)
5.1.5.一、驅動是內核的一部分
(1)驅動已經成爲內核中最龐大的組成部分
(2)內核會直接以函數調用的方式調用驅動代碼(驅動若是有問題,內核就死掉了)
(3)驅動的動態安裝和卸載都會「更改」內核(有點像改裝車)
5.1.5.二、驅動對內核的影響
(1)驅動程序崩潰甚至會致使內核崩潰(也作了一些防禦措施)
(2)驅動的效率會影響內核的總體效率
(3)驅動的漏洞會形成內核安全漏洞
5.1.5.三、常見驅動安全性問題
(1)未初始化指針(野指針)
(2)惡意用戶程序
(3)緩衝區溢出(定義一個buffer來接收應用層的數據,可是應用層發給的數據大於你定義的buf,若是在驅動中作出一些檢驗則能夠避免這種錯誤)
(4)競爭狀態(多個進程同時爭奪某一個共同的資源現象)
【驅動接收應用層傳進來的參數。】
5.1.6.驅動應該這麼學
5.1.6.一、先學好C語言(最重要的前提就是C語言)
5.1.6.二、掌握相關預備知識
(1)硬件操做方面
(2)應用層API
5.1.6.三、驅動學習階段
(1)注重實踐,一步一步寫驅動(本身去寫)
(2)框架思惟(考慮這個代碼的上層被誰調用和下層調用誰),多考慮總體(整個linux體系)和上下層
(3)先經過簡單設備學linux【驅動框架】
(4)學會總結、記錄,這會有助於理解
Linux操做系統包括(linux內核+linux應用程序),其中linux內核包括進程調度、內存管理、虛擬文件系統(字符設備驅動和塊設備驅動)、網絡接口(網絡設備驅動)和進程通訊五個子系統,應用程序好比shell等。
(1)
(2)
內核 驅動 硬件直接的關係:
linux驅動是直接和硬件打交道的軟件程序。層次結構上它處於操做系統和硬件之間。
驅動與linux操做系統內核的關係
1.驅動程序提供的一組設備驅動接口函數DeviceDriverInterface給操做系統。在linux中這一組設備驅動接口函數通常包括open,close,read,write,ioctl等。 這一組函數是經過一個叫作fileoperations的結構體註冊給linux內核的。 ■Linux內核提供特定的系統功能函數進行驅動程序的註冊。註冊時提供設備驅動文件名稱設備號對應的fileoperations結構體fileoperations結構體中存儲有一組設備驅動接口函數指針。
2.驅動程序還須要提供2個模塊接口函數給操做系統。 Linux設備驅動做爲一個linux內核模塊存在。模塊都有2個接口函數---模塊初始化函數和模塊退出函數。上面提到的驅動程序的註冊通常是由模塊初始化函數來實現的。模塊退出函數則用於取消內核註冊釋放資源。 可見只有運行了驅動的這個模塊初始化函數以後驅動程序纔可以被註冊內核才能找到設備驅動。 那麼何時模塊初始化函數纔得到運行呢 ·動態加載時即運行insmode時。 ·靜態加載時模塊編譯進內核系統初始化時會自動調用這個模塊初始化函數。
3.驅動與應用程序的關係 對於應用程序來講驅動所對應的設備文件就表明着驅動。 應用程序經過linux系統提供的API調用使用驅動,咱們寫應用程序就是在寫特定驅動,就是在寫內核。應用程序經過linux文件操做系統調用使用驅動。也就是說設備驅動對於用戶來講同操做一個文件沒有區別。表明這個驅動的是驅動所對應的設備文件。
4.驅動與硬件的關係 硬件對於驅動程序來說能夠抽象爲一組寄存器和須要響應的中斷源。 對於統一尋址的系統好比ARM這一組寄存器就是一段地址空間。 驅動就是按照芯片手冊規定的原則讀取或者寫入這些地址空間。 中斷源是硬件產生的中斷中斷是由內核響應的須要給這個中斷註冊一箇中斷處理函數。這能夠經過調用linux內核提供特定的系統功能函數進行。 通常註冊中斷處理函數能夠在模塊初始化函數裏實現或者在設備驅動接口程序open中實現。
----------------------------------------------------------------------------------------------------------------------------------------------------------
LINUX驅動學習:
(1)驅動程序是硬件的靈魂,也是硬件和系統之間的橋樑。
(2)驅動程序的對象通常是存儲器和外部設備。linux將這些設備分爲3大類:【字符設備、塊設備和網絡設備】
字符設備是指可以一個字節一個字節讀取數據的設備,字符設備通常須要在驅動層實現open(),close(),read(),write()和ioctl()函數。
(3)在linux內核中包含不少實現具體功能的模塊,包括文件系統、網絡協議棧、設備驅動、內核調度、內存管理和進程管理等。
(4)用戶態和內核態:
Linux操做系統分爲用戶態和內核態,用戶態處理上層的軟件工做。內核態用來管理用戶態的程序,完成用戶態的請求的工做。驅動程序與底層的硬件交互,因此工做在內核態。
(5)模塊機制是能夠在運行時加入內核的代碼,使得內核很容易的具備可裁剪性。
(6)靜態裝載和動態裝載:
模塊在內核啓動時裝載稱爲靜態裝載(燒錄成鏡像的形式),模塊在內核已經運行起來時的裝載稱爲動態裝載。
(7)內核程序中包含的頭文件是指內核代碼樹中的內核頭文件,不是指開發應用程序時的外部頭文件,eg:在內核中
實現的庫函數中的打印函數printk()是C語言庫函數printf()的內核版本。
(8)linux操做系統結構由4層組成:用戶層、內核層、驅動層和硬件層。
(9)當內核啓動後,第一件要作的事就是到存儲設備(啓動設備)中尋找根文件系統(包含了使系統運行的主要程序eg:shell和數據),其餘普通的文件系統未來要掛載到根文件系統上來。
(10)內核啓動後運行的第一個程序就是init,其將啓動根文件系統中的shell程序,給用戶提供一個友好的界面。
(11)根文件系統以樹形結構來組織目錄和文件的結構,系統啓動後,根文件系統被掛接到根目錄"/"上,這時候根目錄下就包含了根文件系統的各個目錄和文件。
(12)咱們常使用busybox工具來構建根文件系統,能夠從http://www.busybox.net/downloads下載其相應的版本。
(13)構建驅動程序模塊時,必須考慮驅動程序與內核的兼容性。即便模塊代碼相同,標準內核模塊和特定廠商的內核模塊其模塊格式也是不一樣的。
(14) 驅動模塊 的組成:
一、頭文件(必選) #include<linux/module.h> 和#include<linux/init.h>是必須的
二、模塊參數(可選) 驅動模塊加載時,須要傳遞給驅動模塊的參數
三、模塊功能函數(可選)
四、其餘(可選)
五、模塊加載函數(必須) 模塊的加載函數,有點相似於main()函數
六、模塊卸載函數(必須) 執行後清除了加載函數裏分配的資源
七、模塊許可聲明(必須) 表示模塊受到內核支持的程度,使用MODULE_LICENSE()表示許可權限的程度。
(15)模塊的操做:
1)insmod命令加載模塊
2)rmmod命令卸載模塊
3)lsmod查看模塊加載信息
(16)linux下的驅動主要分爲字符設備驅動、塊設備驅動和網路設備接口驅動。咱們學習驅動就是學習這三類設備提供給咱們的接口。
(17) 靜態編譯(從新下載編譯linux內核)和動態編譯。開發階段以動態編譯(不從新啓動內核)爲主。模塊的方式動態加載。
(18)主設備號區分設備驅動程序。次設備號區分同一個驅動程序建立的多個設備。常見於多個串口和硬盤分區。次設備號一般依次對應同類型的多個設備。
(19)設備驅動的框架:
一、驅動程序的開始------設備的註冊
二、註冊的結構體
三、註冊的fop指針(函數表)
(20)內核程序員得到內存的方式是kmalloc(分配出的地址空間都是物理上連續的),使用方法相似於用戶空間的malloc版本。
kmalloc傳遞不一樣標誌,致使了該函數的不一樣行爲:
GFP_KERNEL
GFP_ATOMIC
GFP_USER
_GFP_DMA
2.4內核中register——char
2.6內核中調用cdev結構體的初始化,fop指針(函數表)要嵌入到這個cdev結構體中