zircon ddk快速入门
# 入門
本文檔是[Driver Development Kit教程](ddk-tutorial.md)文檔的一部分。
編寫設備驅動程序通常被視為一項艱巨的任務,充滿了復雜性,并且需要鮮為人知的內(nèi)核機密的晦澀知識。
本節(jié)的目標是揭開這一過程的神秘面紗;你會學到一切需要知道的如何編寫設備驅動程序的知識。從他們的工作開始,它們?nèi)绾纹鹱饔?#xff0c;以及它們?nèi)绾芜m應整個系統(tǒng)。
##概述
在最高級別,設備驅動程序的工作是為特定設備提供統(tǒng)一的接口,同時隱藏特定于設備實現(xiàn)的細節(jié)。
例如,兩個不同的以太網(wǎng)驅動程序都允許客戶端發(fā)送數(shù)據(jù)包,使用完全相同的C語言函數(shù)輸出接口。每個驅動程序都負責管理自己的硬件,但是,即使硬件不同,客戶端接口相同。
請注意,驅動程序提供的接口可能是“中間”&mdash層面的。也就是說,它們可能不一定代表鏈中的“最終”設備。
考慮一個基于PCI的以太網(wǎng)設備。
首先,需要基本PCI驅動程序,了解如何與PCI總線本身通信。
這個驅動程序對以太網(wǎng)一無所知,但確實知道如何與處理機器上的特定PCI芯片組通信。
它枚舉該總線上的設備,收集來自每個設備上的各種寄存器信息,并提供允許其客戶端(如基于PCI的以太網(wǎng)驅動程序)執(zhí)行PCI操作的功能,比如分配中斷或DMA通道。
因此,這個基本PCI驅動程序為以太網(wǎng)驅動程序提供服務,以太網(wǎng)驅動程序來管理其相關硬件。
同時,其他設備(如視頻卡)也可以使用基本PCI驅動程序以類似的方式管理其硬件。
##zircon模型
為了提供最大的靈活性,Zircon世界的驅動允許綁定到匹配的“父”設備,并發(fā)布自己的“兒子”。
此層次結構根據(jù)需要進行擴展:一個驅動程序可能只發(fā)布一個子項,另一個驅動程序認為該子項是其parent,第二個驅動程序發(fā)布自己的child,等等。
為了理解其工作原理,讓我們按照基于PCI的以太網(wǎng)示例進行操作。
系統(tǒng)首先提供一個特殊的“PCI root”父級。
實際上,它說的是“我知道當你在這個系統(tǒng)上有一個PCI總線,當你找到它時,把它綁定在*這里*?!?/p>
>下面的“高級主題”部分提供了有關此過程的更多詳細信息。
驅動程序由系統(tǒng)(搜索目錄)和驅動程序進行評估匹配自動綁定。
在這種情況下,綁定到“PCI root”父級的驅動程序找到了,并綁定了。
這是基本的PCI驅動程序。它的工作是配置PCI總線,并枚舉總線上的外設。
PCI總線具有關于如何識別外圍設備的特定約定:
供應商ID(** VID **)和設備ID(** DID **)的組合是所有可能的PCI設備的唯一標識。
在枚舉期間,將從外設和新父級讀取這些值,發(fā)布包含檢測到的VID和DID(以及其他主機)的節(jié)點信息)。
每次發(fā)布新設備時,都會執(zhí)行與上述相同的重復過程(像最初的PCI root設備發(fā)布一樣);
也就是說,系統(tǒng)會評估驅動程序,搜索匹配的驅動程序是否符合新父母的特點。
而對于PCI根設備,我們之前在搜索匹配某種功能(稱為“協(xié)議”,我們很快就會看到這一點)的驅動程序,但是,在這種情況下,我們將搜索匹配不同協(xié)議的驅動程序,即滿足“是一個PCI設備且有給定的VID和DID”的協(xié)議要求。
如果找到合適的驅動程序(一個匹配所需的協(xié)議,VID和DID),它將與父母綁定。
作為綁定的一部分,我們初始化驅動程序—這涉及此類操作,如設置card進行操作,啟動接口,和發(fā)布此設備的一個或多個子設備。
對于PCI以太網(wǎng)驅動程序,它發(fā)布“以太網(wǎng)”接口,同時符合另一種協(xié)議,稱為“以太網(wǎng)實現(xiàn)”協(xié)議。
該協(xié)議代表了一種與客戶使用(但刪除了一步;我們將回到此處)功能相近的通用協(xié)議。
###協(xié)議
我們上面提到了三個協(xié)議:
* PCI根協(xié)議(`ZX_PROTOCOL_PCIROOT`),
* PCI設備協(xié)議(`ZX_PROTOCOL_PCI`),和
*以太網(wǎng)實現(xiàn)協(xié)議(`ZX_PROTOCOL_ETHERNET_IMPL`)。
括號中的名稱是與協(xié)議對應的C語言常量,供參考。
什么是協(xié)議?
協(xié)議是嚴格的接口定義。
以太網(wǎng)驅動程序發(fā)布了一個符合`ZX_PROTOCOL_ETHERNET_IMPL`的接口。
這意味著它必須提供在數(shù)據(jù)結構中定義的一組函數(shù)(在本案例中是`ethmac_protocol_ops_t`)。
這些功能對于實現(xiàn)協(xié)議的所有設備都是通用的 - ?mdash;例如,
所有以太網(wǎng)設備必須提供查詢該MAC地址功能的接口。
其他協(xié)議當然對它們的功能有不同的要求,必須提供。
例如,塊設備將發(fā)布符合“塊實現(xiàn)協(xié)議”(`ZX_PROTOCOL_BLOCK_IMPL`)的接口,必須提供`block_protocol_ops_t`定義的函數(shù)。
該協(xié)議包括一個以塊為單位返回設備大小的函數(shù)。
我們將在以下章節(jié)中研究這些協(xié)議。
#高級主題
上面介紹了zircon驅動器的全景圖,重點是協(xié)議。
在本節(jié)中,我們將研究一些高級主題,例如平臺相關的主題和平臺無關的代碼解耦,
“雜項”協(xié)議,以及協(xié)議和進程的映射方式。
##平臺依賴與平臺無關
上面,我們提到`ZX_PROTOCOL_ETHERNET_IMPL`是“接近”由客戶端使用的函數(shù),但這個接口將會被刪除。那是因為還有一個協(xié)議,`ZX_PROTOCOL_ETHERNET`,介于客戶端和驅動兩者之間。
此附加協(xié)議用于處理所有以太網(wǎng)驅動程序的通用函數(shù)(以避免代碼重復)。
此類功能包括緩沖區(qū)管理,狀態(tài)報告和管理功能。
這實際上是“平臺依賴”與“平臺無關”的解耦;
公共代碼存在于平臺獨立部分(一次),而特定于驅動程序的代碼在平臺相關部分中實現(xiàn)。
這種架構(套路)在多個地方都有使用。
例如,對于塊設備,硬件驅動程序綁定到總線(例如,PCI),并提供`ZX_PROTOCOL_BLOCK_IMPL`協(xié)議。
獨立于平臺的驅動程序綁定到`ZX_PROTOCOL_BLOCK_IMPL`,并發(fā)布面向客戶的協(xié)議,`ZX_PROTOCOL_BLOCK`。
您還可以通過顯示控制器,I<sup>2</sup>C總線和串行驅動程序看到這一點。
##雜項協(xié)議
在[simple drivers](simple.md)中,我們展示了幾個驅動程序的代碼基本功能,但不提供與特定協(xié)議相關的服務(即,它們不是“以太網(wǎng)”或“塊”設備)。
這些驅動程序綁定到`ZX_PROTOCOL_MISC_PARENT`。
> @@@更多內(nèi)容?
##進程/協(xié)議映射
為了使討論保持簡單,我們沒有討論進程分離,因為它與驅動有關。
要了解這些問題,讓我們看看其他操作系統(tǒng)如何處理它們,并將其與zircon方法進行比較。
在宏內(nèi)核(如Linux)中,許多驅動程序都在內(nèi)核中實現(xiàn)。
這意味著它們共享相同的地址空間,并且有效地生活在同一個“進程”中。
這種方法的主要問題是故障隔離/利用。
壞驅動程序可以取出整個內(nèi)核,因為它位于同一個地址空間中,因此具有對所有內(nèi)核內(nèi)存和資源的特權訪問。
受損的驅動程序可能出于同樣的原因而出現(xiàn)安全威脅。
另一個極端,在一些微內(nèi)核操作系統(tǒng)中,將每個驅動程序服務都放在自己的進程中。
它的主要缺點是如果一個驅動程序依賴于另一個驅動程序的服務,
內(nèi)核至少會影響兩個驅動進程的上下文切換操作(如果不是數(shù)據(jù)傳輸)。
雖然微內(nèi)核操作系統(tǒng)通常對這種操作設計得很快,但是高頻率的調用它們也是不合需求的。
Zircon采用的方法基于設備主機(** devhost **)的概念。
devhost是一個包含協(xié)議棧的進程&mdash;也就是說,一個或更多協(xié)同工作的協(xié)議。
devhost從ELF共享庫加載驅動程序(稱為動態(tài)共享對象,或** DSO **)。
在[simple drivers](simple.md)部分中,我們將看到meta信息包含在DSO中以加快發(fā)現(xiàn)過程。
協(xié)議棧有效地允許為設備創(chuàng)建完整的“驅動程序”,由平臺相關和平臺獨立組件組成,在一個獨立的過程容器中。
對于高級閱讀器,請查看Zircon命令行可用的`dm dump`命令。
它顯示設備樹,并顯示進程ID,DSO名稱和其他有用的信息。
這是一個高度編輯的版本,僅顯示PCI以太網(wǎng)驅動程序部分:
```
1. [root]
2. ? ?[sys]
3. ? ? ? <sys> pid=1416 /boot/driver/bus-acpi.so
4. ? ? ? ? ?[acpi] pid=1416 /boot/driver/bus-acpi.so
5. ? ? ? ? ?[pci] pid=1416 /boot/driver/bus-acpi.so
? ? ? ? ? ? ...
6. ? ? ? ? ? ? [00:02:00] pid=1416 /boot/driver/bus-pci.so
7. ? ? ? ? ? ? ? ?<00:02:00> pid=2052 /boot/driver/bus-pci.proxy.so
8. ? ? ? ? ? ? ? ? ? [intel-ethernet] pid=2052 /boot/driver/intel-ethernet.so
9. ? ? ? ? ? ? ? ? ? ? ?[ethernet] pid=2052 /boot/driver/ethernet.so
```
從上面可以看到進程ID“1416”(第3到6行)是"高級配置和電源接口"(** ACPI **)驅動程序,
通過DSO`bus-acpi.so`實現(xiàn)。
在主枚舉期間,ACPI DSO檢測到PCI總線。
這導致parent發(fā)布了`ZX_PROTOCOL_PCI_ROOT`(第5行,導致`[pci]`條目的出現(xiàn))
然后導致devhost加載`bus-pci.so` DSO并綁定到它。
DSO是我們上面討論的在整個過程中引用的“基本PCI驅動程序”。
在綁定期間,基本PCI驅動程序枚舉了PCI總線,并找到了以太網(wǎng)卡(第6行檢測總線0,設備2,功能0,顯示為“[00:02:00]”)。
(當然,還發(fā)現(xiàn)了許多其他設備,但簡單起見,我們已將它們從上面列出中移除)。
然后,檢測到此設備會導致基本PCI驅動程序發(fā)布使用`ZX_PROTOCOL_PCI`和設備的VID和DID新parent。
此外,創(chuàng)建了一個新的devhost(進程ID“2052”)并加載了`bus-pci.proxy.so` DSO(第7行)。
此代理充當從新devhost(pid`2052`)到基本PCI驅動(pid`1416`)的接口。
>這是“切斷”設備驅動程序只在自己進程的地方&mdash;新的devhost和基本的PCI驅動程序現(xiàn)在在兩個不同的進程中。
新的devhost`2052`然后找到一個匹配的child(`intel-ethernet.so`第8行的DSO;它被認為是匹配的,因為它有'ZX_PROTOCOL_PCI`和正確VID和DID)。
DSO發(fā)布了一個`ZX_PROTOCOL_ETHERNET_IMPL`,它綁定到一個匹配的child(第9行的`ethernet.so` DSO;它被認為是匹配的,因為它有一個`ZX_PROTOCOL_ETHERNET_IMPL`協(xié)議)。
這個鏈沒有顯示的是最終的DSO(`ethernet.so`)發(fā)布了一個`ZX_PROTOCOL_ETHERNET`&mdash;這是客戶端可以使用的部分,所以當然不會涉及進一步的“設備”綁定。
?
總結
以上是生活随笔為你收集整理的zircon ddk快速入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器人学习笔记(一)
- 下一篇: C++ QT中国象棋项目讲解(四) 简单