驅動的分層分離概念——platform機制剖析
- 硬件平臺:韋東山嵌入式Linxu開發板(S3C2440.v3)
- 軟件平臺:運行於VMware Workstation 12 Player下UbuntuLTS16.04_x64 系統
- 參考資料:《嵌入式Linux應用開發手冊》、《嵌入式Linux應用開發手冊第2版》
- 開發環境:Linux 2.6.22.6 內核、arm-linux-gcc-3.4.5-glibc-2.3.6工具鏈
一、回顧
在上一篇博文【輸入子系統——框架分析】中,分析了輸入子系統的框架如下圖所示:
- 在整個框架中,
input.c
文件起一個中轉的作用; - 純代碼相關的文件
xxx_handler.c
,用來存放相對“穩定”的代碼(穩定——基本不需要修改、兼容性強); - 硬件有關的文件
xxx_device.c
,用來進行具體硬件驅動的編寫,一般只需要編寫這個文件。 - 對於整個系統,在已經有
xxx_handler.ko
初次加載xxx_device.ko
時:會調用input_register_device()
將該device
註冊進輸入子系統(放入鏈表並進行匹配),匹配成功後之後調用input_attach_handler()
找到對應handler->connect()
建立連接。
對於上述的圖,我們可以很清晰的看到,整個輸入子系統大致被分爲三個部分:中轉部分input.c
、穩定部分xxx_handler.c
、編寫部分xxx_device.c
。
在Linux系統中,有一個名詞來描述這種類型的機制:platform(總線)機制。
二、platform機制
1、分層思想
把核心層與設備相關層分開出來,每一層專注於自己的功能的編寫,核心層特點:供多數文件使用的共用代碼,供設備相關層調用。
如上圖的input.c
爲核心層,xxx_device.c
與xxx_driver.c
爲設備硬件相關層(platform機制中的handler稱爲driver)。
2、分離
把硬件相關的代碼與驅動相關的分離開來,如上圖中編寫部分xxx_device.c
爲硬件相關的代碼,穩定部分xxx_driver.c
爲驅動相關。
3、機制剖析
對於上述中的中轉部分input.c
、穩定部分xxx_handler.c
、編寫部分xxx_device.c
,三者構成的是device-bus-driver
體系。
3.1 device部分
platform機制中,這個文件一般命名爲xxx_dev.c
,用來進行具體硬件驅動的編寫,一般只需要編寫這個文件。
通過分析,得到下圖:
- 構建一個
platform_device
結構體xxx_dev
原型:
- 需要通過
platform_device_register()
來註冊一個平臺devicexxx_dev
- 調用
device_add()
來添加xxx_dev
- 進行插入鏈表且匹配工作
3.2 driver部分
platform機制中,這個文件一般命名爲xxx_drv.c
,用來存放相對“穩定”的代碼(穩定——基本不需要修改、兼容性強)。
通過分析,得到下圖:
- 構建一個
platform_driver
結構體xxx_drv
原型:
- 需要通過
platform_driver_register()
來註冊一個平臺driverxxx_drv
- 調用
bus_add_driver
來添加xxx_drv
- 進行插入鏈表工作(這裏並沒有進行匹配)
3.3 bus部分
在上面介紹了device部分
與driver部分
,那麼二者是怎麼來進行匹配的呢?下面分兩種情況來介紹:
-
先加載
xxx_drv.ko
,後加載xxx_dev.ko
。
在加載xxx_dev.ko
時會進行如下:
①、將xxx_dev
結構體放入到bus的device鏈表中
②、從bus的drv鏈表中每取出一個drv
,就調用bus->match()
函數判斷drv是否支持這個dev
③、若支持則調用drv->probe()
函數 -
先加載
xxx_dev.ko
,後加載xxx_drv.ko
。
在加載xxx_drv.ko
時會進行如下:
①、將xxx_drv
結構體放入到bus的driver鏈表中
②、從bus的device鏈表中每取出一個dev
,就調用bus->match()
函數判斷dev是否支持這個drv
③、若支持則調用drv->probe()
函數
那麼他們是如何進行判斷是否互相支持的呢?
這裏只是一種匹配方式,還有其他幾種,可以查看這片博文https://blog.csdn.net/shenlong1356/article/details/104461673
在drivers/base/bus.c
中找到如下代碼