<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 14.6.?集成起來 為更好理解驅動模型做什么, 讓我們通覽一個設備在內核中的生命周期的階段. 我們描述 PCI 子系統如何與驅動模型交互, 一個驅動如何被加入和去除的基本概念, 以及一個設備如何從系統中被加入和去除. 這些細節, 即便特別地描述 PCI 內核代碼, 適用所有其他的使用驅動核心來管理它們的驅動和設備的子系統. PCI 核心, 驅動核心和單獨的 PCI 驅動之間的交互是非常復雜, 如同圖 [創建設備過程](# "圖?14.3.?創建設備過程")所示. **圖?14.3.?創建設備過程** ![創建設備過程](https://box.kancloud.cn/2015-09-02_55e6d9e884e44.png) ### 14.6.1.?添加一個設備 PCI 子系統聲明一個單個 struct bus_type 稱為 pci_bus_type, 它使用下列值初始化: ~~~ struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, .hotplug = pci_hotplug, .suspend = pci_device_suspend, .resume = pci_device_resume, .dev_attrs = pci_dev_attrs, }; ~~~ 這個 pci_bus_type 變量被注冊到驅動內核, 當 PCI 子系統通過對 bus_register 的調用被加載入內核時. 當這個發生時, 驅動核心創建一個 sysfs 目錄在 /sys/bus/pci 里, 它包含 2 個目錄: devices 和 drivers. 所有的 PCI 驅動必須定義一個 struct pci_driver 變量, 它定義了這個 PCI 驅動能夠做的不同的功能(更多的關于 PCI 子系統和如何編寫一個 PCI 驅動的信息, 見 12 章). 那個結構包含一個 struct device_driver, 它接著被 PCI 核心初始化, 當 PCI 驅動被注冊時. ~~~ /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; drv->driver.probe = pci_device_probe; drv->driver.remove = pci_device_remove; drv->driver.kobj.ktype = &pci_driver_kobj_type; ~~~ 這個代碼為驅動建立總線來指向 pci_bus_type 以及使 probe 和 remove 函數來指向 PCI 核心內的函數. 驅動的 kobject 的 ktype 被設置為變量 pci_driver_kobj_type, 為使 PCI 驅動的屬性文件正常工作. 接著 PCI 核心注冊 PCI 驅動到驅動核心: ~~~ /* register with core */ error = driver_register(&drv->driver); ~~~ 驅動現在準備好被綁定到任何一個它支持的 PCI 設備. PCI 核心, 在來自特定結構的實際和 PCI 總線交談的代碼的幫助下, 開始探測 PCI 地址空間, 查找所有的 PCI 設備. 當一個PCI 設備被發現, PCI 核心在內存中創建一個 struct pci_dev 類型的新變量. struct pci_dev 結構的一部分看來如下: ~~~ struct pci_dev { /* ... */ unsigned int devfn; unsigned short vendor; unsigned short device; unsigned short subsystem_vendor; unsigned short subsystem_device; unsigned int class; /* ... */ struct pci_driver *driver; /* ... */ struct device dev; /* ... */ }; ~~~ 這個 PCI 設備的總線特定的成員被 PCI 核心初始化( devfn, vendor, device, 和其他成員), 并且 struct device 變量的 parent 變量被設置為這個 PCI 設備所在的 PCI 總線設備. bus 變量被設置指向 pci_bus_type 結構. 接下來 name 和 bus_id 變量被設置, 根據讀自 PCI 設備的 name 和 ID. 在 PCI 設備結構被初始化之后, 設備被注冊到驅動核心, 使用: ~~~ device_register(&dev->dev); ~~~ 在 device_register 函數中, 驅動核心初始化設備的許多成員, 注冊設備的 kobject 到 kobject 核心( 它導致一個熱插拔事件產生, 但是我們在本章后面討論), 接著添加設備到驅動的 parent 所持有的設備列表中. 完成這個使所有的設備可被以正確的順序瀏覽, 一直知道每一個位于設備層次中哪里. 設備接著被添加到所有設備的總線特定的列表中, 在本例中, pci_bus_type 列表. 接著注冊到這個總線的所有驅動的列表被檢查, 并且總線的匹配功能被調用給每個驅動, 指定這個設備. 對于 pci_bus_type 總線, 匹配函數被 PCI 核心設定為指向 pci_bus_match 函數, 在設備被提交給驅動核心前. pci_bus_match 函數轉換驅動核心傳遞給它的 struct device 為一個 struct pci_dev. 它還轉換 struct device_driver 為一個 struct pci_driver , 并接著查看設備的 PCI 設備特定信息和驅動, 看是否這個驅動聲明它能夠支持這類設備. 如果匹配不成功, 函數返回 0 給驅動核心, 并且驅動核心移向列表中的下一個驅動. 如果匹配成功, 函數返回 1 給驅動核心. 這使驅動核心設置struct device 中的驅動指針指向這個驅動, 并且接著調用在 struct device_driver 中特定的 probe 函數. 早些時候, 在 PCI 驅動注冊到驅動核心之前, probe 變量被設為指向 pci_device_probe 函數. 這個函數轉換(又一次) struct device 為一個struct pci_dev, 在設備中設置的 struct driver 為一個 struct pci_driver. 它再次驗證這個驅動聲明它可以支持這個設備( 這意味著一個重復的額外檢查, 某些未知的原因), 遞增設備的引用計數, 并且接著調用 PCI 驅動的 probe 函數, 用一個指向它應當被綁定到的 struct pci_dev 結構的指針. 如果這個 PCI 驅動的 probe 函數認為它不能處理這個設備由于某些原因, 它返回一個負的錯誤值, 這個值被傳遞回驅動核心并且使它繼續深入設備列表來和這個設備匹配一個. 如果這個 probe 函數能夠認領這個設備, 它做所有的需要的初始化來正確處理這個設備, 并且接著它返回 0 給驅動核心. 這使驅動核心來添加設備到當前被這個特定驅動所綁定的所有設備列表, 并且創建一個符號連接到這個它現在控制的設備, 在這個驅動在 sysfs 的目錄. 這個符號連接允許用戶準確見到哪個設備被綁定到哪個設備. 這可被見到, 如: ~~~ $ tree /sys/bus/pci /sys/bus/pci/ |-- devices | |-- 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0 | |-- 0000:00:00.1 -> ../../../devices/pci0000:00/0000:00:00.1 | |-- 0000:00:00.2 -> ../../../devices/pci0000:00/0000:00:00.2 | |-- 0000:00:02.0 -> ../../../devices/pci0000:00/0000:00:02.0 | |-- 0000:00:04.0 -> ../../../devices/pci0000:00/0000:00:04.0 | |-- 0000:00:06.0 -> ../../../devices/pci0000:00/0000:00:06.0 | |-- 0000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.0 | |-- 0000:00:09.0 -> ../../../devices/pci0000:00/0000:00:09.0 | |-- 0000:00:09.1 -> ../../../devices/pci0000:00/0000:00:09.1 | |-- 0000:00:09.2 -> ../../../devices/pci0000:00/0000:00:09.2 | |-- 0000:00:0c.0 -> ../../../devices/pci0000:00/0000:00:0c.0 | |-- 0000:00:0f.0 -> ../../../devices/pci0000:00/0000:00:0f.0 | |-- 0000:00:10.0 -> ../../../devices/pci0000:00/0000:00:10.0 | |-- 0000:00:12.0 -> ../../../devices/pci0000:00/0000:00:12.0 | |-- 0000:00:13.0 -> ../../../devices/pci0000:00/0000:00:13.0 | `-- 0000:00:14.0 -> ../../../devices/pci0000:00/0000:00:14.0 `-- drivers |-- ALI15x3_IDE | `-- 0000:00:0f.0 -> ../../../../devices/pci0000:00/0000:00:0f.0 |-- ehci_hcd | `-- 0000:00:09.2 -> ../../../../devices/pci0000:00/0000:00:09.2 |-- ohci_hcd | |-- 0000:00:02.0 -> ../../../../devices/pci0000:00/0000:00:02.0 | |-- 0000:00:09.0 -> ../../../../devices/pci0000:00/0000:00:09.0 | `-- 0000:00:09.1 -> ../../../../devices/pci0000:00/0000:00:09.1 |-- orinoco_pci | `-- 0000:00:12.0 -> ../../../../devices/pci0000:00/0000:00:12.0 |-- radeonfb | `-- 0000:00:14.0 -> ../../../../devices/pci0000:00/0000:00:14.0 |-- serial `-- trident `-- 0000:00:04.0 -> ../../../../devices/pci0000:00/0000:00:04.0 ~~~ ### 14.6.2.?去除一個設備 一個 PCI 可用多個不同的方法被從系統中去除. 所有的 card-bus 設備在一個不同的物理因素上是真正的 PCI 設備, 并且內核 PCI 核心不區分它們. 允許在機器運行時加減 PCI 設備的系統正變得更加普遍, 并且 Linux 支持它們. 還有一個偽 PCI 熱插拔驅動允許開發者來測試看是否他們的 PCI 驅動正確處理系統運行中的設備去除. 這個模塊稱為 fakephp 并且使內核認為 PCI 設備已消失, 但是它不允許用戶物理上從系統中去除一個 PCI 設備, 這個系統沒有合適的硬件來這樣做. 見這個驅動的文檔來獲取更多關于如何使用它測試你的 PCI 驅動的信息. PCI 核心發揮了不少于它增加設備的努力到去除它. 當一個 PCI 設備要被去除, pci_remove_bus_device 函數被調用. 這個函數做一些 PCI-特定 的清理和日常工作, 并且接著使用一個指向 struct pci_dev 的 struct device 成員的指針調用 device_unregister 函數. 在 device_unregister 函數中, 驅動核心只從綁定到這個設備(如果有)的驅動解除連接 sysfs 文件, 從它的內部設備列表中去除這個設備, 并且使用指向包含在 struct device 結構中的 struct kobject 的指針調用 kobject_del. 這個函數用一個 hotplug 調用到用戶空間來聲明 kobject 現在被從系統中去除, 并且接著它刪除所有的和 kobject 關聯的 sysfs 文件以及這個 kobject 起初已創建的 sysfs 目錄自身. kobject_del 函數也去除設備自身的 kobject 引用. 如果那個引用是最后一個( 意味著沒有用戶空間文件為這個 sysfs 的設備入口而打開 ), 接著是 PCI 設備自身的 release 函數, pci_release_dev, 被調用. 這個函數只釋放 struct pci_dev 占用的內存. 此后, 所有的和這個設備關聯的 sysfs 入口被去除, 并且和這個設備關聯的內存被釋放. PCI 設備現在完全從系統中被去除. ### 14.6.3.?添加一個驅動 一個 PCI 驅動被添加到 PCI 核心, 當它調用 pci_register_driver 函數時. 這個函數只初始化 struct device_driver 結構, 這個結構包含在 struct pci_driver 結構里面, 如同之前在關于添加設備的一節中提過的. 接著 PCI 核心使用指向包含在 struct pci_driver 結構中的 sturct device_driver 結構的指針調用在驅動核心的 driver_register 函數. driver_register 函數初始化在 struct device_driver 結構中的幾個鎖, 并且接著調用 bus_add_driver 函數. 這個函數進行下面的步驟: - 查找驅動要被關聯的總線. 如果這個總線被發現, 函數立刻返回. - 驅動的 sysfs 目錄被創建, 基于驅動的名子和它被關聯的總線. - 總線的內部鎖被獲取, 接著所有的已經注冊到總線的設備被檢查, 匹配函數為它們被調用, 就象當一個新設備被添加時. 如果那個匹配函數成功, 接著剩下的綁定過程發生, 如同在前面章節描述過的. ### 14.6.4.?去除一個驅動 去除一個驅動是一個非常容易的動作. 對于一個 PCI 驅動, 驅動調用 pci_unregister_driver 函數. 這個函數只調用驅動核心函數 driver_unregister, 使用一個指向傳遞給它的 struct pci_driver 的 struct devie_driver 的指針. deiver_unregister 函數處理一些基本的日常工作, 通過清理某些在 sysfs 樹中連接到這個驅動入口的 sysfs 屬性. 它接著列舉所有的連接到這個驅動的設備并且為它調用 release 函數. 發生這個恰好象前面提過的 release 函數, 當一個設備從系統中去除時. 在所有的設備從驅動中被解綁定后, 驅動代碼完成這個獨特的邏輯: ~~~ down(&drv->unload_sem); up(&drv->unload_sem); ~~~ 這就在返回函數的調用者之前完成. 這個鎖被獲取因為代碼需要等待所有的對這個驅動的引用計數在它可安全返回前掉到 0. 需要這樣是因為 driver_unregister 函數最普遍被作為一個要卸載的模塊退出的路徑來調用. 模塊需要保留在內存只要驅動被設備引用并且等待這個鎖被釋放, 這允許內核知道當可以安全從內存去除驅動時.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看