這本《Linux內核修煉之道》已經開賣(網上的連接爲: 卓越、噹噹、china-pub ),雖然是嚴肅文學,但爲了保證流暢性,大部分文字我還都是斟詞灼句,反覆的念幾遍才寫上去的,儘可能考慮到寫上去的每段話可以讓讀者產生什麼疑惑,而後也都會緊接着儘可能的去進行解釋清楚,中間的不少概念也有反覆糾結過怎麼解釋可以更容易的理解,力求即便對於初學者也能夠有不多阻礙的一氣讀完。同時我也把書中一部分本身的感悟抽出來整理了精華版,share出來。固然水平有限,錯漏之處有發現而修訂時遺漏的,也有尚沒有發現的。這本書若是對您有用,乃我之幸事,若是無用,就在此先坐臥不安的向你們拜個不是了。linux
下面仍然是以前5月份一次presentation的部份內容及講義,不過當時的題目叫「驅動開發的方法論」,或許對你們有用吧。至於這幾回講座的視頻貌似網上都能找到。面試
************************************************************************緩存
第一個緣由是:目前幾乎全部的驅動開發方面的參考書,內容結構都是先介紹介紹什麼是 linux 驅動,它分爲哪些種類,而後是各類類型設備的驅動程序的內容細節。大都是隻注重各類驅動自己的細節,而沒有站在一個全局總體的角度講解一下驅動開發的方法。這樣致使的後果就是,大多數的驅動開發者雖然能夠正確的編寫驅動程序,但每每都是隻知其一不知其二,知其然而不知其因此然。網絡
第二個緣由是:目前不少驅動開發者,即便是已經有多年經驗的開發者,在開發驅動的時候也就是填充填充 driver 的結構體,對於比較成熟的平臺,就是網上找個相似的驅動修改一下,即便寫十個百個千個驅動,也就是對某些硬件比較熟,遇到全新的芯片全新的平臺就一籌莫展。應該說這樣對驅動的理解是頗有限的。這也是目前 linux 驅動開發領域的現狀。socket
咱們首先認識一下 linux 驅動的基本面,咱們認識一個新事物的的第一件事就是了解它的一些基本信息,就像咱們人與人之間互相認識首先也是經過我的的基本信息同樣。函數
linux 驅動在本質上就是一種軟件程序,上層軟件能夠在不用瞭解硬件特性的狀況下,經過驅動提供的接口,和計算機硬件進行通訊。工具
系統調用是內核和應用程序之間的接口,而驅動程序是內核和硬件之間的接口,也就是內核和硬件之間的橋樑。它爲應用程序屏蔽了硬件的細節,這樣在應用程序看來,硬件設備只是一個設備文件,應用程序能夠象操做普通文件同樣對硬件設備進行操做。學習
linux 驅動程序是內核的一部分,管理着系統中的設備控制器和相應的設備。它主要完成這麼幾個功能:對設備初始化和釋放;傳送數據到硬件和從硬件讀取數據;檢測和處理設備出現的錯誤。視頻
通常來講,一個驅動能夠管理一種類型的設備。例如不一樣的 U 盤都屬於 mass storage 設備,咱們不須要爲每個 U 盤編寫驅動,而只須要一個驅動就能夠管理全部這些 mass storage 設備。接口
爲方便咱們加入各類驅動來支持不一樣的硬件,內核抽象出了不少層次結構,這些層次結構是 linux 設備驅動的上層。它們抽象出各類的驅動接口,驅動只須要填寫相應的回調函數,就能很容易把新的驅動添加到內核。
通常來講, linux 驅動能夠分爲三類,就是塊設備驅動,字符設備驅動和網絡設備驅動。塊設備的讀寫都有緩存來支持,而且塊設備必須可以隨機存取。塊設備驅動主要用於磁盤驅動器。
而字符設備的 I/O 操做沒有經過緩存。字符設備操做以字節爲基礎,但不是說一次只能執行一個字節操做。例如對於字符設備咱們能夠經過 mmap 一次進行大量數據交換。字符設備實現比較簡單和靈活。
網絡設備在 Linux 裏作專門的處理。 Linux 的網絡系統主要是基於 BSD 的 socket 機制。網絡設備驅動爲網絡操做提供接口,管理網絡數據的接送和收發。爲了屏蔽網絡環境中物理網絡設備的多樣性, Linux 對全部的物理設備進行抽象並定義了一個統一的概念,稱之爲接口( interface )。全部對網絡硬件的訪問都是經過接口進行的,接口對上層協議提供一致化的操做集合來處理基本數據的發送和接收,對下層屏蔽硬件差別。它與字符設備及塊設備不一樣之處其一就是網絡接口不存在於 Linux 的設備文件系統 /dev/ 中。
和前一篇的介紹同樣,看完外表,咱們再看內涵,就是 Linux 驅動的工做流程。大概有四個部分:使用 insmod 加載,模塊的初始化,進行設備操做,使用 rmmod 卸載。
Linux 驅動有兩種存在形式,一種是直接編譯進內核,就是咱們在配置內核的時候,在相應選項上選 Y ,另一種就是編譯成模塊,按需加載和卸載。一般咱們使用 insmod 命令完成模塊的加載,在加載時還能夠指定模塊參數。另一個經常使用的加載工具是 modprobe ,它與 insmod 的不一樣在於它會檢查模塊之間的依賴關係,將該模塊依賴的模塊也加載到內核。
每一個驅動都有本身的初始化函數,完成一些新功能的註冊,這個初始化函數只是在初始化的時候被使用。在 linux 系統裏,設備以文件的形式存在,應用程序能夠經過 open 、 read 等函數操做設備,經過設備文件實現對設備的訪問。設備再也不使用時,咱們使用 rmmod 命令來卸載它,卸載的過程會調用到驅動的推出函數,每一個驅動都必須有一個退出函數,沒有的話,內核就不會容許去卸載它。
在對 linux 驅動的外表和內涵都有了一個初步的認識以後,咱們來看看做爲一個驅動開發者,咱們須要注意哪些問題。
首先,對模塊機制的瞭解是開發 linux 驅動的基礎,由於咱們編寫驅動的過程也就是在編寫一個內核模塊的過程。早期版本的內核是總體式的,也就是說全部的部分都靜態地鏈接成一個很大的執行文件。可是如今的內核採用的是新的機制,即模塊機制:許多功能包含在模塊內,當你須要時可使用 insmod 去擁抱它,將它動態地載入到內核裏,當你不須要時,則可使用 rmmod 將它一腳踢開。這就使得 kernel 的內核很小,並且在運行的時候能夠不用 reboot 就可以載入和替代模塊。
其次,咱們要注重對設備模型的理解。其實從 2.6 內核開始,隨着設備模型的出現,驅動的開發就再也不是個困難的問題,絕不誇張得說,理解了設備模型,再去看那些五花八門的驅動程序,你會發現本身站在了另外一個高度,從而有了一種俯視的感受,就像鳳姐俯視知音和故事會,韓峯同志俯視女下屬。不過貌似大部分驅動開發者都沒意識到這個問題。
最後,是要養成使用協議的 spec 、設備的 datasheet 、內核參考代碼去解決問題的習慣,而不是一碰到問題就處處尋找所謂的牛人去問怎麼解決。
中間的那些內容和前面精華版的博文裏差很少,就不貼了,…………
前面介紹了我我的感受開發驅動須要注意的三個方面,如今說個實際的例子。前些天一個網友在本身的 csdn 博客上寫了篇文章,名字就叫給 fudan_abc 的一封信,信裏說了本身的問題,我以爲應該不少人都存在這樣相似的問題,這裏我們來看一下。
先說他我的的狀況:有必定的 linux c 基礎,熟悉 linux 內核 / 驅動的開發環境搭建和編譯。如今想作個 i2c 芯片的 驅動,該驅動要跑在 x86 平臺上。
手邊的資料有:
1. 芯片手冊 看了幾回,基本瞭解 上邊的 資源和 他的 i2c 地址
2. 找到 linux + arm 平臺上的 對應的 .c 文件和 .h 文件。可是對應的 arm 平臺的 kernel source 沒有。
3. .c 文件裏的 代碼看過 一遍,從函數名 能夠知道他的功能。
而後開始 操做 怎麼移植這個 i2c 芯片到 x86 平臺上。以後遇到了一些列的問題,好比 i2c 的地址信息等等,具體我就不敘述了。
而後他就去請教了一些人
請教某人 A : 「 其實 i2c 很簡單,你填充那個 driver 結構體就 ok 了。 」 我反問 「 我對裏邊的 流程和調用不熟悉啊 「
A 回: 」 你把他們想象成一個黑盒就能夠了 」 我: 「 沒法想象,我怎麼想象?我想看看裏邊的代碼究竟是怎樣的。 」A:"....." 。 對 A 的請教結果,沒法解決個人問題:我到底該怎麼辦?
再請教 B:
B:「 其實 i2c 移植就是註冊那幾個函數 , 你想看內核代碼實現,內核這麼大你怎麼可能搞清楚,我作了那麼多移植,有時候連芯片手冊都搞不清,直接 prink 吧代碼給調出來的 」 我: 「 。。。 」 沒法理解,無話可說。
其實這裏邊的 A 和 B 說的也沒錯,不少人寫驅動大概就這麼作的,可是這樣子就是寫成百上千個驅動也不能說就理解 linux 驅動了,面試時碰到的絕大部分人都屬於這種狀況,能回答本身作了什麼,但一談到一些相關的基本的問題就每每回答不上來。
我以爲首要的問題是缺少好奇心,作技術的好奇心應該是原動力,特別對於搞 linux 內核和驅動的,好奇心有多強,你的水平就可能會增加到多高。
其次,對於作驅動的來講,對於 2.6 內核,重要的是去理解設備模型,不少人都本末倒置了,不少專門寫驅動的書也不注重設備模型的理解,只去應付一種種類型的協議和設備的驅動,即便寫個一萬個也僅僅是對比較成熟的芯片熟了些。並且,不理解設備驅動,難道寫驅動的時候不以爲不少東西很朦朧麼?這也是我我的以爲很奇怪的一方面。
像我以前設備模型的文章裏說的那樣,理解了設備模型,對各類類型的驅動就有種俯視的感受了。這個時候再你去看特定類型的協議和設備的實現,脈絡就很清晰,好比你看 i2c 的實現。這個時候重要的就是 i2c 的協議,具體芯片的 datasheet ,加上看看內核裏現有的 i2c 驅動做爲參考,就是我所說的驅動開發的三件寶。
因此說若是但願作 2.6 的驅動話,關鍵仍是要先去理解下設備模型,將這個比較抽象的概念在內心形象化,而後再去看具體的驅動比較好。