linux設備驅動學習總結-keyPoints

1、linux設備模型把linux驅動分爲三部分:總線、設備、驅動,設備與驅動相對獨立,由總線負責設備和驅動的匹配,設備註冊匹配驅動,驅動註冊匹配設備。

2、linux內核充分體現了面向對象的思想,爲了實現高內聚,低耦合的軟件模型,linux驅動儘量的把獨立的功能模塊分離出來,分離的手段是通過分層,比如設備和驅動分出一個總線層,做到了設備和驅動的分離;分出一個input層,做到了輸入設備和文件操作(file_ops)的分層;I2c分出一個核心層,做到了I2c adapter和I2c client的分離。類似的案例在linux驅動中比比皆是。這樣做的好處是,降低了程序的耦合,提高了驅動程序的可移植性。

3、對於依附在所有總線(platform總線,I2c總線,spi總線等等)的設備驅動而言,他們有一些固定的特性,比如他們都有一個xxx_driver的結構體,platform總線上的設備驅動有platform_driver結構,I2C總線上的設備驅動有i2c_driver,spi總線上的設備驅動有spi_driver結構,這些結構的內容也基本大同小異,提供了probe,remove,suspend,resume的接口,同時會提供一個device_driver的結構體實例成員,這個結構體成員描述了xxx_driver(xxx是總線名字)在驅動意義上的一些共性,它裏面有一個bus_type的成員用來描述總線屬性,一般這個結構會在總線設備層被實例化,比如platform定義了platform_bus_type,正式有了這個bus_type,所有驅動能和總線,以及依附與總線上的設備關聯起來。以依附在platform總線上的設備驅動爲例,有如下代碼:

bus_type的實例的match函數指針,指定了該總線上設備和驅動的匹配規則。

4、在2.6版本以及之前版本內核,對設備的描述都是用c語言實現的,存儲在/kernel_source/arch/plat/mach_xxxx目錄下。3.x之後,對設備的描述體現在設備樹文件,原來的板級文件不再使用,但是設備的基本結構沒有變化,只是由內核負責讀取fdt(flattened device tree),然後展開成2.6版本同樣的結構,可以稱爲edt(expanded device tree)。

5、在sysfs下的各個目錄都有該設備的可讀寫屬性,比如/sys/class/graphics/fb0/bits_per_pixel文件,可以用來讀取、設置液晶屏的位深屬性。這個文件的生成跟attribute結構體緊密相連,代碼如下: 

從上面的代碼可以看出,內核還是很面向對象的,類似C++的繼承。

事實上,sysfs中的目錄來源於bus_type、device_driver、device,而目錄中的文件則來源與attribute。Linux內核中也定義了一些快捷方式以方便attribute結構的創建工作。

6、下面的這段代碼可以遍歷整個sysfs,並且dump出來總線、設備、和驅動信息,如果去掉#註釋,還可以爲整個系統中的設備建立/dev下的設備節點

7、linux產生競態主要三種情況:中斷、搶佔、多處理器。一個cpu運行在進程上下文或者中斷上下文(且這段上下文是臨界區域)的時候可能被中斷打斷;被其它進程搶佔;或者其它的cpu也要訪問臨界區域。這個時候就會發生競態。

8、linux下產生競態主要有中斷、搶佔、多處理器這三種情況。避免中斷產生的競態,可以提前關閉中斷,處理完成後在開啓中斷;避免搶佔產生的競態,可以使用spin_lock,因爲自旋鎖鎖住的臨界區域是不可搶佔的,但是要求臨界區域儘量的短。另外在關閉中斷的情況下搶佔的競態也不會發生,因爲linux內核的進程調度也依賴中斷實現;針對多處理器產生的競態,通常也是使用spin_lock,或者互斥鎖也可以,至於什麼時候使用互斥鎖,什麼時候使用自旋鎖,參考第11條。(另外2.6.35後,取消了中斷嵌套,所以中斷與中斷產生的競態可以不用擔心了)

9、針對前兩條,做一個情景分析。假如cpu運行在中斷上下文,中斷和搶佔產生的競態都不需要考慮,因爲,2.6.35後,中斷嵌套被取消,且中斷上下文的優先級要高於進程上下文(搶佔本身是進程搶佔,運行在進程上下文),需要考慮的是多處理器產生的競態,參考上一條,多處理器產生的競態可以用spin_lock或者互斥鎖來避免,但是中斷不允許睡眠(互斥鎖在拿不到鎖的情況下會進入睡眠)所以必須使用spin_lock;假如cpu運行在進程上下文,則中斷、搶佔、多處理器這三種情況都需要考慮,避免競態的辦法參考上一條。

10、spin_lock在單處理器的情況下,自動退化爲互斥鎖(宋寶華說的,不知道是不是真的這樣)。而實際上,spin_lock在單處理器情況下沒有任何意義,想象一下單處理器運行在進程上下文,spin_lock鎖住的區域可能產生競態的情況只有中斷,如果中斷中也要訪問這段臨界區域,假如中斷拿不到鎖,那就徹底掛了(因爲他會自旋,且我們只有一個cpu),如果順利拿到鎖,說實在的在單處理器中沒有任何意義。

11、什麼情況下用自旋鎖,什麼情況下用互斥鎖?

首先,在臨界區較小,佔用cpu時間較短,或者任務的實時性要求較高的情況下使用自旋鎖,可避免CPU頻繁調度產生的開銷。

其次,有可能引起阻塞的臨界區絕對不可以使用自旋鎖,阻塞意味着進程切換,切換到的進程如果也要spin_lock加鎖,死鎖就產生了。

最後,在中斷和軟中斷中的臨界區域,儘量使用自旋鎖(這種情況也符合第一條,因爲中斷是實時性要求較高的任務),如果一定要用互斥鎖,也要try_lock,因爲中斷程序不能睡眠。


持續補充中........

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章