學(xué)Linux驅動(dòng):應先了解總線(xiàn)驅動(dòng)模型

發(fā)布時(shí)間:2020-5-19 15:30    發(fā)布者:嵌入式人生17
學(xué)Linux驅動(dòng):應先了解總線(xiàn)驅動(dòng)模型
[導讀] Linux設備林林總總,嵌入式開(kāi)發(fā)一個(gè)繞不開(kāi)的話(huà)題就是設備驅動(dòng)開(kāi)發(fā),在做具體設備驅動(dòng)開(kāi)發(fā)之前,有必要對Linux設驅動(dòng)模型有一個(gè)相對清晰的認識,將會(huì )幫助驅動(dòng)開(kāi)發(fā),明白具體驅動(dòng)接口操作符相應都做些什么。
個(gè)人對于驅動(dòng)模型的理解概括起來(lái)就是一句話(huà):利用面向對象編程思想,實(shí)現設備分層管理軟件體系結構。
注:代碼分析基于linux-5.4.31
為啥要驅動(dòng)模型
隨著(zhù)系統結構演化越來(lái)越復雜,Linux內核對設備描述衍生出一般性的抽象描述,形成一個(gè)分層體系結構,從而引入了設備驅動(dòng)模型。這樣描述還是不夠讓人理解,來(lái)看一下這些需求就好理解些:
· Linux內核可以在各種體系結構和硬件平臺上運行,因此需要最大限度地提高代碼在平臺之間的可重用性。
· 分層實(shí)現也實(shí)現了軟件工程的高內聚-低耦合的設計思想。低耦合體現在對外提供統一的抽象訪(fǎng)問(wèn)接口,高內聚將相關(guān)度緊密的集中抽象實(shí)現。
· Linux內核驅動(dòng)程序模型是先前在內核中使用的所有不同驅動(dòng)程序模型的統一。它旨在通過(guò)將一組數據和操作整合到全局可訪(fǎng)問(wèn)的數據結構中,來(lái)擴展基于基礎總線(xiàn)來(lái)橋接設備驅動(dòng)程序。
傳統的驅動(dòng)模型為它們所控制的設備實(shí)現了某種類(lèi)似于樹(shù)的結構(有時(shí)只是一個(gè)列表)。不同類(lèi)型的總線(xiàn)之間沒(méi)有任何一致性。
驅動(dòng)模型抽象了啥
當前驅動(dòng)程序模型為描述總線(xiàn)和總線(xiàn)下可能出現的設備提供了一個(gè)通用的、統一的模型。統一總線(xiàn)模型包括一組所有總線(xiàn)都具有的公共屬性和一組公共回調,如總線(xiàn)探測期間的設備發(fā)現、總線(xiàn)關(guān)閉、總線(xiàn)電源管理等。
通用的設備和橋接接口反映了現代計算機的目標:即執行無(wú)縫設備“即插即用”,電源管理和熱插拔的能力。特別是,英特爾和微軟規定的模型(即ACPI)可確保與x86兼容的系統上幾乎任何總線(xiàn)上的幾乎所有設備都可以在此范式下工作。當然,雖然大多數總線(xiàn)都支持其中大多數操作,但并不是每條總線(xiàn)都能夠支持所有此類(lèi)操作。
那么哪些通用需求被抽象出來(lái)了呢?
·
電源系統和系統關(guān)機,對于電源管理與系統關(guān)機對于設備相關(guān)的操作進(jìn)行抽象實(shí)現。關(guān)機為什么要被抽象出來(lái)管理,比如設備操作正在進(jìn)行此時(shí)系統收到關(guān)機指令,那么在設備模型層就會(huì )遍歷系統設備硬件,確保系統正確關(guān)機。
·
·
用戶(hù)空間訪(fǎng)問(wèn)sysfs虛擬文件系統實(shí)現與設備模型對外的訪(fǎng)問(wèn)抽象,這也是為什么說(shuō)Linux 設備也是文件的由來(lái)。實(shí)際從軟件架構層面看,這其實(shí)是一個(gè)軟件橋接模塊,抽象出統一用戶(hù)訪(fǎng)問(wèn)接口,橋接了設備驅動(dòng)。
·
·
熱插拔管理:熱插拔管理機制定義統一的抽象接口操作符kset_hotplug_ops,不同設備利用操作符實(shí)現差異化。
·
·
設備類(lèi)型:設備分類(lèi)機制,從高層級抽象描述設備類(lèi)型,具體可以在sysfs下面體現。
·
用戶(hù)空間訪(fǎng)問(wèn)
由于具有系統中所有設備的完整分層視圖,因此將完整的分層視圖導出到用戶(hù)空間變得相對容易。這是通過(guò)實(shí)現名為sysfs虛擬文件系統來(lái)完成的。
sysfs的自動(dòng)掛載通常是通過(guò)/etc/fstab文件中的以下條目來(lái)完成的:
none /sys sysfs defaults 0 0
對于Debian系統而言,可能在/lib/init/fstab采用下面的形式掛載:
none /sys sysfs nodev,noexec,nosuid 0 0
當然也可以采用手動(dòng)方式掛載:
# mount -t sysfs sysfs /sys
當將設備插入樹(shù)中時(shí),都會(huì )為其創(chuàng )建一個(gè)目錄。該目錄可以填充在發(fā)現的每個(gè)層(全局層,總線(xiàn)層或設備層)中。
全局層當前創(chuàng )建兩個(gè)文件-'name'和'power'。前者報告設備名稱(chēng)。后者報告設備的當前電源狀態(tài)。它還將用于設置當前電源狀態(tài)。
總線(xiàn)層為探測總線(xiàn)時(shí)發(fā)現的設備創(chuàng )建文件。例如,PCI層當前為每個(gè)PCI設備創(chuàng )建“ irq”和“resource”文件。
特定于設備的驅動(dòng)程序也可以在其目錄中導出文件,以暴露特定于設備的數據或可用接口。
驅動(dòng)模型實(shí)現
先來(lái)梳理一下內部幾個(gè)主要與驅動(dòng)模型相關(guān)的數據結構:
./include/linux/Device.h 定義設備驅動(dòng)主要數據結構
· bus_type:抽象描述總線(xiàn)類(lèi)型,如USB/PCI/I2C/MMC等
· device_driver:實(shí)現具體連接在總線(xiàn)上的設備驅動(dòng)。
· device:描述連接在總線(xiàn)上的設備
./include/linux/Kobject.h中定義了隱藏在后臺的類(lèi)似于基類(lèi)的數據結構:
· kset:可以認為是kobject的頂層容器類(lèi)。每個(gè)kset內部都包含了自己的kobject.
· kobject:在 sysfs 中出現的每個(gè)對象都對應一個(gè) kobject, 它和內核交互來(lái)創(chuàng )建它的可見(jiàn)表述,每一個(gè) kobject 對應 文件系統 /sys 里的一個(gè) 目錄,目錄的名字就是結構體中的 name
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml11608\wps7.jpg
bus_type
bus_type用以驅動(dòng)總線(xiàn),具體的驅動(dòng)USB/I2C/PCI/MMC等:
· 注冊總線(xiàn),利用bus_register注冊總線(xiàn),bus_unregister刪除總線(xiàn)。如下例子,每種總線(xiàn)須定義一個(gè)bus_type對象,并利用bus_register注冊總線(xiàn),或bus_unregister刪除總線(xiàn)。
/*i2c-core-base.c*/
struct bus_type i2c_bus_type = {
.name  = "i2c",
.match  = i2c_device_match,
.probe  = i2c_device_probe,
.remove  = i2c_device_remove,
.shutdown = i2c_device_shutdown,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);
static int __init i2c_init(void)
{
int retval;

retval = of_alias_get_highest_id("i2c");

down_write(&__i2c_board_lock);
if (retval >= __i2c_first_dynamic_bus_num)
  __i2c_first_dynamic_bus_num = retval + 1;
up_write(&__i2c_board_lock);
    /*注冊I2C總線(xiàn)*/
retval = bus_register(&i2c_bus_type);
if (retval)
  return retval;

is_registered = true;

#ifdef CONFIG_I2C_COMPAT
i2c_adapter_compat_class = class_compat_register("i2c-adapter");
if (!i2c_adapter_compat_class) {
  retval = -ENOMEM;
  goto bus_err;
}
#endif
retval = i2c_add_driver(&dummy_driver);
if (retval)
  goto class_err;

if (IS_ENABLED(CONFIG_OF_DYNAMIC))
  WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));
if (IS_ENABLED(CONFIG_ACPI))
  WARN_ON(acpi_reconfig_notifier_register(&i2c_acpi_notifier));

return 0;

class_err:
#ifdef CONFIG_I2C_COMPAT
class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
is_registered = false;
    /*錯誤時(shí)刪除總線(xiàn)*/
bus_unregister(&i2c_bus_type);
return retval;
}
· 注冊適配器驅動(dòng)程序(USB控制器,I2C適配器等),以檢測連接的設備,并提供與設備的通信機制
· 圖中的match函數接口用于將驅動(dòng)程序與設備進(jìn)行匹配。match回調的目的是使總線(xiàn)有機會(huì )通過(guò)比較驅動(dòng)程序支持的設備ID與特定設備的設備ID來(lái)確定特定驅動(dòng)程序是否支持特定設備,而不會(huì )犧牲特定于總線(xiàn)的功能或類(lèi)型安全性 。當向總線(xiàn)注冊驅動(dòng)程序時(shí),將遍歷總線(xiàn)的設備列表,并為每個(gè)沒(méi)有與之關(guān)聯(lián)的驅動(dòng)程序的設備調用match回調。
· 提供API函數以實(shí)現適配器驅動(dòng)以及設備驅動(dòng)。
· 同時(shí)dev_pm_ops *pm實(shí)現對于總線(xiàn)的功耗管理接口抽象。對于特定總線(xiàn)實(shí)現這個(gè)操作符對應的函數。
struct dev_pm_ops {
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
};
· iommu_ops 操作符提供總線(xiàn)相關(guān)的IOMMU抽象。
· 設備驅動(dòng)注冊到總線(xiàn)上時(shí),將在sysfs管理總線(xiàn)/設備/設備驅動(dòng)的層次關(guān)系,以PCI為例:
/*在總線(xiàn)上注冊的驅動(dòng)程序會(huì )在總線(xiàn)的驅動(dòng)程序目錄中獲得一個(gè)目錄*/
/sys/bus/pci/
        |-- devices
        `-- drivers
            |-- Intel ICH
            |-- Intel ICH Joystick
            |-- agpgart
            `-- e100
/*在該類(lèi)型的總線(xiàn)上發(fā)現的每個(gè)設備都會(huì )在總線(xiàn)的設備目錄中獲得到物理層次結構中該設備目錄的符號鏈接*/
/sys/bus/pci/
          |-- devices
          |   |-- 00:00.0 -> ../../../root/pci0/00:00.0
          |   |-- 00:01.0 -> ../../../root/pci0/00:01.0
          |   `-- 00:02.0 -> ../../../root/pci0/00:02.0
          `-- drivers
· 總線(xiàn)屬性:bus_groups/設備屬性dev_groups/驅動(dòng)屬性drv_groups。
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml11608\wps8.jpg
device
·
作用:抽象描述具體的設備
·
·
設備注冊:發(fā)現設備的總線(xiàn)驅動(dòng)程序使用下面的函數來(lái)向內核注冊設備
·
int device_register(struct device * dev);
· 利用device_unregister()從總線(xiàn)上刪除設備
device_driver
· 作用:抽象描述連接在總線(xiàn)上的具體設備的驅動(dòng)
· 驅動(dòng)注冊,通過(guò)下面的函數將設備驅動(dòng)程序注冊
int driver_register(struct device_driver *drv);
· 使用它使用以下命令從驅動(dòng)程序目錄中添加和刪除屬性
  int driver_create_file(struct device_driver *, const struct driver_attribute *);
  void driver_remove_file(struct device_driver *, const struct driver_attribute *);
class
· 作用:抽象設備的高層視圖,描述的是設備的集合。抽象了同類(lèi)型的設備的底層實(shí)現細節。比如所有的網(wǎng)絡(luò )接口都位于/sys/class/net下
· struct subsys_private *p描述類(lèi)鏈表
kobject/kset
· kobject類(lèi)似于面向對象中的內核基類(lèi),內核利用它將各個(gè)對象連接起來(lái)組成分層的機構體系,其parent指針將形成一個(gè)樹(shù)狀分層結構。
· kset內部包含了kobject。重心在描述對象的聚集于集合。這也是set一詞的含義。每一個(gè)kset添加到系統中,都將在sysfs中創(chuàng )建一個(gè)目錄
· kobject/kset一起實(shí)現了sysfs虛擬文件系統中設備/總線(xiàn)/設備驅動(dòng)樹(shù)狀分層結構的最關(guān)鍵的底層實(shí)現由來(lái)。
總體上而言:
通過(guò)上面一些關(guān)鍵數據結構關(guān)系分析,總線(xiàn)設備驅動(dòng)模型最終目的是實(shí)現如下這樣一個(gè)分層驅動(dòng)模型。
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml11608\wps9.jpg

本文地址:http://selenalain.com/thread-589243-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页