本文系轉載,著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。linux
做者: 宋寶華算法
來源: 微信公衆號linux閱碼場(id: linuxdev)設計模式
《設計模式》這本經典的書裏面定義了20多種設計模式,雖然都是面向對象的,彷佛須要C++、Java這樣的語言才能實現,可是根據筆者前面反覆強調的,Linux內核雖然是用C語言和彙編語言寫成,可是其實也處處充滿了面向對象的設計。面向對象更多的是一種思想,而不是一個語言。咱們能夠用C語言實現極大的OO,Linux內核處處都有OO。微信
好比,在Linux的設備驅動框架中,就用了一種很是經典簡單的設計模式——模板方法(Template Method),固然還有一些其餘的設計模式。而設計模式牛逼的地方在於,高手每每不經意之間已經用到了設計模式,甚至本身都不知道。若是高手沒有系統地學習過設計模式,這其實不見得是一個問題。這並不意味着它不懂設計模式,只是他本身都不知道本身用到了哪一個模式。而設計模式學習的終極目的,固然也是忘記設計模式,這個跟練獨孤九劍沒什麼區別,到最後實際上是無招勝有招。架構
模板方法這個模式,強調定義一個基類,這個基類實現了通用的流程和算法。好比作一件事情須要通過step1()、step2()、step3()。那麼咱們定義一個基類:框架
而其中的step1()、step2()、step3()、step4()具體如何實現則是因人而異,因此咱們從baseClass類裏面,繼承出來的類裏面,實現step1()、step2()、step3()這樣的代碼,override掉baseClass裏面的函數。ide
這樣的設計讓外部不關心derivedClass,由於流程和接口都是在基類的。而基類實現的doSomething()成員函數,是對外的接口。這個UML關係是很是簡單的:函數
在Linux設備驅動裏面,大量存在相似的設計,咱們以NAND爲例子。在drivers/mtd/nand/nand_base.c這層裏面,定義了NAND的一些操做流程。性能
好比寫OOB的代碼:學習
它這個裏面要走cmdfunc()、write_buf()、cmdfunc()、waitfunc()這些步驟,這些步驟,不論是全世界哪一個NAND的硬件,都是同樣的通用的,可是具體的不一樣的NAND硬件控制器,實現這些步驟中涉及到的cmdfunc()等函數的實現方法卻因人而異。
譬如freescale的版本fsl_elbc_nand.c就是:
nand_base.c這個C文件是NAND的中間層,它很是相似咱們前面說的實現baseClass這一層的代碼,nand_write_oob_std函數相似baseClass :: doSomething。而Linux驅動中定義的nand_chip的各個不一樣的NAND控制器,對nand_chip這個結構體中成員函數cmdfunc()、write_buf()等的實現則是各異的,相似derivedClass裏面override掉step1()、step2()。nand_chip定義在include/linux/mtd/nand.h:
這樣的設計,好處是很是明顯的。特定的硬件只用管與自身操做相關的事情,而通用的流程,都由nand_base搞定,最大程度上減少了具體實例的代碼量,也最大程度上覆用了中間層的代碼。
這樣的例子無處不在,好比咱們在LCD的中間層:
本文後語不搭前言,請見諒。最近有不少童鞋詢問筆者,作Linux驅動有沒有前途?筆者明確地告訴你們:根本沒有前途!可是前途是本身賺的,這依賴你從驅動進去,可是從更大的視角出來:
經過作驅動理解不少OO的架構設計思想,昇華本身高內聚和低耦合的理解,把本身變成一個更高level的software engineer;
經過作驅動,進一步理解Linux自己的進程、內存、IO等知識,昇華對軟件系統和性能分析的理解,把本身變成一個更高level的技術expert。
若是作了5年驅動,進入的時候是調試寄存器搞示波器,出來的時候仍是調寄存器搞示波器,那天然是徹底沒有什麼前途的!
有沒有前途,這個事情,徹底是因人而異的。前途是無所謂有,無所謂無的。你若是有抽象、衍生的能力和不斷學習總結的精神,不管是作驅動仍是不作驅動,都會是頗有前途的事情。反之,作什麼基本都沒前途。
更多精彩更新中……歡迎關注微信公衆號:linux閱碼場(id: linuxdev)