Linux設備模型之——註冊接口的使用

前言

平時寫驅動或者看一份驅動代碼的時候,經常被各種註冊接口函數搞暈,到底什麼時候用哪一個呢?這個問題必須要在理解了Linux的設備模型後纔能有個清晰的概念,本文只是在閱讀了網上一些大神的博客後的一些小小的總結。不過本文暫時不會對Linux的設備模型有過多的深入,只是在自己的理解上,理清一下注冊接口之間的關係。

正文

先來看一下我們在驅動開發過程中,最常接觸到的兩個結構體。

1、device和device_driver

這兩個結構體是驅動開發的基礎,顧名思義,device就是設備的抽象,device_driver就是驅動的抽象。結構體都比較複雜,但是好在註釋比較清晰,具體可以參考:include\linux\device.h。驅動開發中接觸最多的就是怎麼使用這些接口,所以我們先看一下這些使用步驟。

下面以hid總線(bus)、uhid設備(device)、hid-generic驅動(device_driver)爲例子,講述一下流程,代碼目錄爲:drivers\hid\。

1.1、bus

因爲這一小節重點講device和device_driver,所以bus的概念我們先放一邊。註冊hid總線的代碼在:drivers\hid\hid-core.c

1.2、device

分配一個struct device類型的變量,填充必要的信息後,把它註冊到內核中。

代碼目錄:
drivers\hid\uhid.c

函數調用關係:
uhid_char_open //分配了uhid_device結構體,其中就包含了struct device
->uhid_device_add_worker
    ->hid_add_device
        ->device_add //這個函數就是將分配到的device註冊到內核中,並在這個過程中匹配合適的device_driver
            ->bus_probe_device //註冊進總線
                ->device_attach
                    ->__device_attach
                        ->driver_match_device //最終會調用driver的match函數

1.3、device_driver

分配一個struct device_driver類型的變量,填充必要的信息後,把它註冊到內核中

代碼目錄:
drivers\hid\hid-generic.c

函數調用關係:
module_hid_driver //分配的struct hid_driver就包含了struct device_driver
->__hid_register_driver
    ->driver_register
        ->bus_add_driver //將driver加到bus上
            ->driver_attach //匹配對應的device

1.4、小結

所以我們可以看到,註冊device用的device_add接口(或者device_register、device_create_vargs和device_create,不過它們最終都是調用device_add);註冊device_driver用的driver_register接口。不過實際開發中,除了直接用device和device_driver,也會用,在這兩個結構體封裝上的其他結構體,比如下一小節要講的內容。

2、platform_device和platform_driver

系統中,每個設備都需要連接到一個bus上,這個bus可以是一個實際存在的內部bus、虛擬的bus或者是platform bus。這一小節我們主要關注platform bus。

那麼連接到platform bus的platform device又有哪些呢?kernel在platform.txt中有相關的定義,總的來說就是,platform device包括:基於端口的設備(已不推薦使用,保留下來只爲兼容舊設備,legacy);連接物理總線的橋設備;集成在SOC上的各種控制器;連接在其他bus上的設備等等。

platform bus基於底層的bus模塊,抽象出來的一個虛擬的platform bus,用於platform設備的連接;platform device基於底層的device模塊,用於表示platform設備;platform driver基於底層的driver模塊,用於驅動platform設備。

其實從platform device和platform driver兩個結構體的定義就可以看出,他們是和struct device和struct device_driver有着千絲萬縷的關係。具體的定義可以參考:include\linux\platform_device.h。下面我們只是看一下怎麼用系統提供的API。

2.1、struct platform_device

代碼路徑:
drivers\base\platform.c

函數調用關係:
platform_device_register
->platform_device_add
    ->device_add

從函數調用關係來看,最終還是走到了device_add,也進一步說明platform_device是在device上的一層封裝而已。還有其它的註冊接口可以參考include\linux\platform_device.h

2.2、struct platform_driver

代碼路徑:
linux\platform_device.h

函數調用關係:
platform_driver_register
->__platform_driver_register
    ->driver_register  //類似於platform_device,最終也是調用到註冊device_driver的函數

2.3、platform bus

想註冊device和driver,當然需要有對應的bus,而platform bus的註冊在drivers\base\platform.c的platform_bus_init實現。細節就不過多說了,有興趣的同學可以自行查閱代碼。

2.4、小結

上面只是提到了一些API,具體的驅動代碼例子可以參考我以前寫的文章:設備、驅動、總線模型簡介

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