衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何正確認識Linux設驅動模型

Linux愛好者 ? 來源:逸珺 ? 作者:逸珺 ? 2020-09-13 09:30 ? 次閱讀

[導讀] Linux設備林林總總,嵌入式開發一個繞不開的話題就是設備驅動開發,在做具體設備驅動開發之前,有必要對Linux設驅動模型有一個相對清晰的認識,將會幫助驅動開發,明白具體驅動接口操作符相應都做些什么。

個人對于驅動模型的理解概括起來就是一句話:利用面向對象編程思想,實現設備分層管理軟件體系結構。

注:代碼分析基于linux-5.4.31

為啥要驅動模型

隨著系統結構演化越來越復雜,Linux內核對設備描述衍生出一般性的抽象描述,形成一個分層體系結構,從而引入了設備驅動模型。這樣描述還是不夠讓人理解,來看一下這些需求就好理解些:

Linux內核可以在各種體系結構和硬件平臺上運行,因此需要最大限度地提高代碼在平臺之間的可重用性。

分層實現也實現了軟件工程的高內聚-低耦合的設計思想。低耦合體現在對外提供統一的抽象訪問接口,高內聚將相關度緊密的集中抽象實現。

Linux內核驅動程序模型是先前在內核中使用的所有不同驅動程序模型的統一。它旨在通過將一組數據和操作整合到全局可訪問的數據結構中,來擴展基于基礎總線來橋接設備驅動程序。

傳統的驅動模型為它們所控制的設備實現了某種類似于樹的結構(有時只是一個列表)。不同類型的總線之間沒有任何一致性。

驅動模型抽象了啥

當前驅動程序模型為描述總線和總線下可能出現的設備提供了一個通用的、統一的模型。統一總線模型包括一組所有總線都具有的公共屬性和一組公共回調,如總線探測期間的設備發現、總線關閉、總線電源管理等。

通用的設備和橋接接口反映了現代計算機的目標:即執行無縫設備“即插即用”,電源管理和熱插拔的能力。特別是,英特爾和微軟規定的模型(即ACPI)可確保與x86兼容的系統上幾乎任何總線上的幾乎所有設備都可以在此范式下工作。當然,雖然大多數總線都支持其中大多數操作,但并不是每條總線都能夠支持所有此類操作。

那么哪些通用需求被抽象出來了呢?

電源系統和系統關機,對于電源管理與系統關機對于設備相關的操作進行抽象實現。關機為什么要被抽象出來管理,比如設備操作正在進行此時系統收到關機指令,那么在設備模型層就會遍歷系統設備硬件,確保系統正確關機。

用戶空間訪問:sysfs虛擬文件系統實現與設備模型對外的訪問抽象,這也是為什么說Linux 設備也是文件的由來。實際從軟件架構層面看,這其實是一個軟件橋接模塊,抽象出統一用戶訪問接口,橋接了設備驅動。

熱插拔管理:熱插拔管理機制定義統一的抽象接口操作符kset_hotplug_ops,不同設備利用操作符實現差異化。

設備類型:設備分類機制,從高層級抽象描述設備類型,具體可以在sysfs下面體現。

用戶空間訪問

由于具有系統中所有設備的完整分層視圖,因此將完整的分層視圖導出到用戶空間變得相對容易。這是通過實現名為sysfs虛擬文件系統來完成的。

sysfs的自動掛載通常是通過/etc/fstab文件中的以下條目來完成的:

none /syssysfs defaults 0 0

對于Debian系統而言,可能在/lib/init/fstab采用下面的形式掛載:

none /sys sysfs nodev,noexec,nosuid 0 0

當然也可以采用手動方式掛載:

# mount -t sysfs sysfs /sys

當將設備插入樹中時,都會為其創建一個目錄。該目錄可以填充在發現的每個層(全局層,總線層或設備層)中。

全局層當前創建兩個文件-'name'和'power'。前者報告設備名稱。后者報告設備的當前電源狀態。它還將用于設置當前電源狀態。

總線層為探測總線時發現的設備創建文件。例如,PCI層當前為每個PCI設備創建“ irq”和“resource”文件。

特定于設備的驅動程序也可以在其目錄中導出文件,以暴露特定于設備的數據或可用接口。

驅動模型實現

先來梳理一下內部幾個主要與驅動模型相關的數據結構:

./include/linux/Device.h 定義設備驅動主要數據結構

bus_type:抽象描述總線類型,如USB/PCI/I2C/MMC等

device_driver:實現具體連接在總線上的設備驅動。

device:描述連接在總線上的設備

./include/linux/Kobject.h中定義了隱藏在后臺的類似于基類的數據結構:

kset:可以認為是kobject的頂層容器類。每個kset內部都包含了自己的kobject.

kobject:在 sysfs 中出現的每個對象都對應一個 kobject, 它和內核交互來創建它的可見表述,每一個 kobject 對應 文件系統 /sys 里的一個 目錄,目錄的名字就是結構體中的 name

bus_type

bus_type用以驅動總線,具體的驅動USB/I2C/PCI/MMC等:

注冊總線,利用bus_register注冊總線,bus_unregister刪除總線。如下例子,每種總線須定義一個bus_type對象,并利用bus_register注冊總線,或bus_unregister刪除總線。

/*i2c-core-base.c*/ structbus_typei2c_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); staticint__initi2c_init(void) { intretval; 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總線*/ retval=bus_register(&i2c_bus_type); if(retval) returnretval; is_registered=true; #ifdefCONFIG_I2C_COMPAT i2c_adapter_compat_class=class_compat_register("i2c-adapter"); if(!i2c_adapter_compat_class){ retval=-ENOMEM; gotobus_err; } #endif retval=i2c_add_driver(&dummy_driver); if(retval) gotoclass_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)); return0; class_err: #ifdefCONFIG_I2C_COMPAT class_compat_unregister(i2c_adapter_compat_class); bus_err: #endif is_registered=false; /*錯誤時刪除總線*/ bus_unregister(&i2c_bus_type); returnretval; }

注冊適配器驅動程序(USB控制器,I2C適配器等),以檢測連接的設備,并提供與設備的通信機制

圖中的match函數接口用于將驅動程序與設備進行匹配。match回調的目的是使總線有機會通過比較驅動程序支持的設備ID與特定設備的設備ID來確定特定驅動程序是否支持特定設備,而不會犧牲特定于總線的功能或類型安全性 。當向總線注冊驅動程序時,將遍歷總線的設備列表,并為每個沒有與之關聯的驅動程序的設備調用match回調。

提供API函數以實現適配器驅動以及設備驅動。

同時dev_pm_ops *pm實現對于總線的功耗管理接口抽象。對于特定總線實現這個操作符對應的函數。

structdev_pm_ops{ int(*prepare)(structdevice*dev); void(*complete)(structdevice*dev); int(*suspend)(structdevice*dev); int(*resume)(structdevice*dev); int(*freeze)(structdevice*dev); int(*thaw)(structdevice*dev); int(*poweroff)(structdevice*dev); int(*restore)(structdevice*dev); int(*suspend_late)(structdevice*dev); int(*resume_early)(structdevice*dev); int(*freeze_late)(structdevice*dev); int(*thaw_early)(structdevice*dev); int(*poweroff_late)(structdevice*dev); int(*restore_early)(structdevice*dev); int(*suspend_noirq)(structdevice*dev); int(*resume_noirq)(structdevice*dev); int(*freeze_noirq)(structdevice*dev); int(*thaw_noirq)(structdevice*dev); int(*poweroff_noirq)(structdevice*dev); int(*restore_noirq)(structdevice*dev); int(*runtime_suspend)(structdevice*dev); int(*runtime_resume)(structdevice*dev); int(*runtime_idle)(structdevice*dev); };

iommu_ops 操作符提供總線相關的IOMMU抽象。

設備驅動注冊到總線上時,將在sysfs管理總線/設備/設備驅動的層次關系,以PCI為例:

/*在總線上注冊的驅動程序會在總線的驅動程序目錄中獲得一個目錄*/ /sys/bus/pci/ |--devices `--drivers |--IntelICH |--IntelICHJoystick |--agpgart `--e100 /*在該類型的總線上發現的每個設備都會在總線的設備目錄中獲得到物理層次結構中該設備目錄的符號鏈接*/ /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

總線屬性:bus_groups/設備屬性dev_groups/驅動屬性drv_groups。

device

作用:抽象描述具體的設備

設備注冊:發現設備的總線驅動程序使用下面的函數來向內核注冊設備

intdevice_register(structdevice*dev);

利用dvice_unregister()從總線上刪除設備

device_driver

作用:抽象描述連接在總線上的具體設備的驅動

驅動注冊,通過下面的函數將設備驅動程序注冊

intdriver_register(structdevice_driver*drv);

使用它使用以下命令從驅動程序目錄中添加和刪除屬性

intdriver_create_file(structdevice_driver*,conststructdriver_attribute*); voiddriver_remove_file(structdevice_driver*,conststructdriver_attribute*);

class

作用:抽象設備的高層視圖,描述的是設備的集合。抽象了同類型的設備的底層實現細節。比如所有的網絡接口都位于/sys/class/net下

struct subsys_private *p描述類鏈表

kobject/kset

kobject類似于面向對象中的內核基類,內核利用它將各個對象連接起來組成分層的機構體系,其parent指針將形成一個樹狀分層結構。

kset內部包含了kobject。重心在描述對象的聚集于集合。這也是set一詞的含義。每一個kset添加到系統中,都將在sysfs中創建一個目錄

kobject/kset一起實現了sysfs虛擬文件系統中設備/總線/設備驅動樹狀分層結構的最關鍵的底層實現由來。

總體上而言:

通過上面一些關鍵數據結構關系分析,總線設備驅動模型最終目的是實現如下這樣一個分層驅動模型。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 驅動
    +關注

    關注

    12

    文章

    1851

    瀏覽量

    85648
  • Linux
    +關注

    關注

    87

    文章

    11345

    瀏覽量

    210406

原文標題:學Linux驅動:應先了解總線驅動模型

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何正確認識電感?

    雖然一直知道,電感的作用,但是具體到那些參數是比較重要的?如何理解這些參數?求解。{:1:}
    發表于 07-18 19:36

    正確認識計算機硬件的安全維護措施有哪些

    正確認識計算機硬件的安全維護措施有哪些科技論文瀏覽:1次摘 要: 論文摘要:對于硬盤而言,維護它的安全只要盡量避免較大的震動即可。現階段,我們所使用的硬盤多是機械硬盤,內部結構精密且復雜,一旦發生
    發表于 09-08 08:18

    正確認識鉛酸蓄電池的修復和蓄電池修復的幾大騙局

    正確認識鉛酸蓄電池的修復和蓄電池修復的幾大騙局   部分故障的蓄電池在一定的程度
    發表于 11-11 14:08 ?1633次閱讀

    如何正確認識繼電器

    如何正確認識繼電器    是根據接收到的某種信號,按控制要求自動開閉水電流控制器路的一類電器。 &
    發表于 12-08 10:16 ?1349次閱讀

    Linux設備驅動模型摘抄

    Linux設備驅動模型摘抄
    發表于 10-31 09:00 ?8次下載
    <b class='flag-5'>Linux</b>設備<b class='flag-5'>驅動</b>的<b class='flag-5'>模型</b>摘抄

    對人工智能的正確認識

    1917年現代藝術核心人物馬塞爾·杜尚在美國紐約展出了一個小便器,并命名為《泉》,這件作品沖擊了當時的藝術觀念,直面藝術與生活的問題。盡管當時《泉》被拒絕展出,但是杜尚的現代藝術觀念影響深遠,之后很多流派都從杜尚那里汲取營養。
    發表于 07-10 13:50 ?8441次閱讀

    正確認識人工智能

    人工智能(AI,Artificial Intelligence)本質上就是為了自學而設計的,有時它的確會出錯。當然,人們可以在事后做出調整,但最好的解決辦法是一開始就防止它發生。那么,如何才能讓人工智能擺脫偏見呢?
    發表于 03-05 14:45 ?2081次閱讀

    關于區塊鏈的正確認識

    每一個人對于區塊鏈認識的不同,最終導致了他們在實踐區塊鏈的方式和方法。雖然最近一段時間以來,數字貨幣的價格不斷上漲,但是,依然有人在區塊鏈的道路上執著前行。縱然是在區塊鏈這條道路上,我們依然看到了公
    的頭像 發表于 01-31 09:53 ?4550次閱讀

    如何正確認識擴音機的輸出功率

    如何正確認識擴音機的輸出功率。
    發表于 04-10 10:11 ?14次下載

    如何正確認識電感鎮流器,電感鎮流器基礎知識詳解

    如何正確認識電感鎮流器?其實關于電感鎮流器的知識,小編之前跟大家說過許多。今天小編就把之前所說過的電感鎮流器知識為大家全新梳理一遍,幫助各位更好的理解電感鎮流器。 當開關閉合電路中施加
    發表于 04-27 17:15 ?2061次閱讀

    你知道有哪幾種人不適合學plc編程嗎?

    缺乏對編程有正確認識的人。想學編程語言就先得做好充分的準備,編程語言難不難?
    的頭像 發表于 07-11 09:55 ?2.9w次閱讀

    Linux驅動:建議先了解總線驅動模型

    [導讀] Linux設備林林總總,嵌入式開發一個繞不開的話題就是設備驅動開發,在做具體設備驅動開發之前,有必要對Linux
    發表于 02-07 11:04 ?3次下載
    學<b class='flag-5'>Linux</b><b class='flag-5'>驅動</b>:建議先了解總線<b class='flag-5'>驅動</b><b class='flag-5'>模型</b>

    Linux總線、設備、驅動模型的探究

    Linux總線、設備、驅動模型的探究
    發表于 02-14 12:01 ?7次下載

    正確認識駕駛輔助系統的局限性

    潛力,”DEKRA德凱董事會成員兼首席技術官 Ulrike Hetzel女士說道。“然而,認識到駕駛輔助系統的局限性也很重要。”
    的頭像 發表于 07-13 14:24 ?1163次閱讀

    電路設計中,如何正確認識磁珠的性能參數?

    電路設計中,如何正確認識磁珠的性能參數? 磁珠是一種常見的電路元件,廣泛應用于濾波器、隔離器和開關電源等電路設計中。為了正確認識磁珠的性能參數,并在電路設計中合理選用和應用磁珠,我們首先需要了解磁珠
    的頭像 發表于 11-22 18:18 ?2373次閱讀
    百家乐存在千术吗| 大世界百家乐官网娱乐网| 百家乐客户端软件| 菲律宾百家乐官网游戏| 大发888 安装包的微博| 百家乐真钱路怎么看| 大世界百家乐官网娱乐网| 克拉克百家乐官网试玩| 德州扑克2| 嘉禾百家乐的玩法技巧和规则 | 百家乐官网解密软件| 三宝娱乐| 大发888娱乐城都有啥扑克牌游戏| 真人百家乐开户须知| 三公百家乐官网在线哪里可以| 百家乐官网百家乐官网论坛| 六合彩图片| 安卓水果机游戏| 百家乐博娱乐平台| 百家乐路单免费下载| 百家乐有技巧么| 百乐坊百家乐官网娱乐城| 赌博百家乐官网的路单| 八大胜备用网址| 德州扑克概率计算| 大发888游戏下载官网免费| 四方百家乐的玩法技巧和规则| 百家乐园zyylc| 属虎和属龙合伙做生意| 竞咪百家乐官网的玩法技巧和规则| 百家乐官网高返水| 保单百家乐官网技巧| 册亨县| 渝北区| 连南| 迁安市| 百家乐官网有人赢过吗| 百家乐官网娱乐全讯网| 榆树市| 长乐坊百家乐官网娱乐城| 网上百家乐官网有人赢过嘛 |