platform driver 是作為一個怎樣的概念出現的?

相對於 char driver 和 block driver, platform主要用來幹什麼?


額... 你每次都邀請一個獵頭解答內核問題, 不合適啊...等我有時間了我幫你邀請幾個內核開發好了.


推薦宋寶華的書和blog,關於platform講了很多。

簡略回答的話,首先要理清楚bus, device 和driver三者的概念。

bus上有driver和device,一個driver可以對應多個device,一個device只能有一個driver。

比如pcie是一種匯流排,intel的82574網卡是一種pcie設備,e1000e.c 是網卡驅動。

因為操作系統要支持外設,必須先要知道當前計算機有哪些設備,以及這些設備的訪問方式、訪問地址、中斷號、中斷觸發方式等。這些資源信息假如寫死在driver代碼里,普通用戶就無法DIY PC了。比如把硬碟換一個sata口,顯卡換一個pcie插槽,控制這些設備的地址和中斷就變了,用戶就得自己改改驅動代碼編譯一下,沒法玩嘛。

這樣就需要把當前計算機有哪些設備,以及這些設備的訪問方式、訪問地址、中斷號、中斷觸發方式等 這些資源信息單獨剝離出來,封進一個一個xxxx_device這樣的結構體里。

這樣xxx_driver也更容易實現 一次編寫,管你x86、arm、powerpc 到處運行。

運行時,每當註冊一個新的xxx_device或者xxx_driver到一條xxx_bus上,linux就嘗試在xxx_bus給這個新加入的xxx_device或者xxx_driver配對(probe),device和driver配對成功了,xxx_driver就能利用xxx_device的內容去控制xxx設備了。

綜上,bus, device 和driver是一個清晰的樹狀結構,一種好的設計。可以在/sys/bus目錄下用ls 、tree命令列出來這個樹。

終於能回到題目,platform 是一種虛擬的bus;而char driver 和 block driver,只是driver的細分。它們並不是並列的關係。那為什麼要有platform 這條虛擬的匯流排呢?

還是上面說的,操作系統要支持外設,必須先要知道當前計算機有哪些設備。要做到這一點,要麼硬體本身能自動探測出來當前bus上有哪些device,要麼就由程序員事先把device資源信息寫在代碼或者dts這類配置文件里。

pci/pcie 匯流排是x86架構的脊椎,且擁有探測pci/pcie 設備的能力。PC上的usb匯流排控制器,對上是一個pcie設備,對下則是usb匯流排的控制器。等於pcie匯流排下擴展出了新的usb匯流排。usb匯流排也是有硬體探測能力的。個人電腦幾乎所有重要的外設:硬碟、u盤、鍵盤、滑鼠、音效卡、顯卡,都是pcie或者usb設備。再加上BIOS的幫助,普通pc的內核幾乎不需要程序員手動註冊一個設備信息,自己就能探測就出來當前計算機插了哪些設備。

但是手機、平板等大量使用SOC的非X86架構計算機,它自己的usb控制器、i2c控制器、音效卡控制器、lcd驅動器、存儲控制器(一般是flash控制器,個別SOC也有sata控制器)等,都不再是X86架構下的pci設備了,靠硬體自己是無法探測的。此時就需要程序員自己手動寫代碼或者配置文件,來註冊這些device的信息。

假如是i2c 設備、spi設備,硬體也沒有探測設備屬性的能力,程序員手動註冊device就註冊了吧,起碼知道是要註冊到那條bus上去。。

可偏偏這些SOC外設並沒有一個統一的匯流排名稱,ARM上叫AHB、 APB ,powerpc上叫CCB,甚至隔個幾年又會發明新的叫法。platform 這條虛擬的bus,就是用來統一維護此類device的bus。

牽一髮動全身的感覺,好累。


大半夜的剛刷完面經過來回答。

其實為什麼要提出設備驅動模型?剛開始也許目的在於提供一個所謂外部觀察視角,再到電源管理。但這個東西真的挺好用的,它可以:解耦

設備驅動應該分成兩個部分,一個是驅動,一個是設備,兩者都有可能發生變化的,而且變化十分多。例如我一個SPI介面,在不同的硬體平台上面基本都會接不同的設備:NAND,LCD,音效卡等等等。以往我們都會將設備驅動寫在一個模塊裡面,比如寫下了一個使用SPI操作NAND的驅動,於是我們沒能向SPI隱藏NAND,當我們需要新的NAND型號的驅動時,就不得不牽連到了SPI。而設備驅動模型的出現,很好地解決了這個問題,現在我們需要編寫兩個內核模塊,一個SPI驅動模塊,一個NAND設備模塊,SPI根本不知道它鏈接的是什麼,要進行什麼樣的操作,直到NAND註冊進去,調用了probe。這樣,驅動的職責十分單一:操作硬體。而如何操作,都是由設備傳遞過來的。這樣,我們需要換一塊其它型號的NAND,只需要修改NAND部分的模塊就行了,就是那個設備模塊,因為SPI根本不知道它要操作的對象,所以SPI不需要修改。故而完成了「將兩個維度的變化因素抽取出來,可以獨立變化」的設計。這可是SPI的對外連接的情形。但是很多情況下,SOC內部許多集成的外設,都沒有像SPI這樣的匯流排連接,而是直接將外設的控制寄存器進行統一編址,用不著這些實際的匯流排。可是,這些實際匯流排的這種模型這麼好用阿,這麼靈活,那些SOC內部集成的外設也想用啊,這樣我們就可以將外設和具體的SOC型號給隔離,比如我們也想讓s3c2410的DMA驅動在s3c2440上使用,這樣我們可以保留DMA作為設備部分,s3c2410和s3c2440相關的代碼作為驅動部分,於是DMA部分代碼就可以不加修改地使用了。既然沒有那些具體連接的匯流排,卻又想用設備驅動模型,而在設備驅動模型裡邊,設備,驅動,匯流排三個組件一個都不能少,既然如此,我們就虛擬一個匯流排好了,這個虛擬的匯流排就叫做platform匯流排。

-------------------------------------------------------------這裡是分割線-----------------------------------------------

對於這個體會還是比較深的,占坑有時間來答


與已有的設備驅動相匹配,接入一些驅動程序的具體實現,如 lcd driver、backlight driver。


推薦閱讀:

如何製造一個內核態的軟鎖死?
如何正確開發 linux bsp?
linux mmap匿名映射的作用是什麼?
segfault at xxx的地址是物理地址還是線性地址,objdump出來的呢?

TAG:操作系統 | 嵌入式系統 | 驅動程序 | Linux內核 |