在 Linux 設備驅動模型中,driver_attach 是驅動程序註冊後,內核自動匹配並綁定對應設備的關鍵函數。本文通過分析 driver_attach、bus_for_each_dev、__driver_attach 及 really_probe 的調用鏈,詳細闡述設備與驅動的自動匹配過程。
driver_attach(struct device_driver *drv)
→ bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)
→ 遍歷總線上的所有設備
→ __driver_attach(struct device *dev, void *data)
→ driver_probe_device(drv, dev)
→ really_probe(dev, drv)
bus_for_each_dev 使用 klist_iter 遍歷掛載在總線上的設備鏈表(bus->klist_devices)。每個 struct device 通過 knode_bus 節點掛載到該鏈表。迭代器支持安全的並發遍歷,包含引用計數管理(kref_get/kref_put)與刪除通知機制(completion)。
drv->bus->match(dev, drv),如 USB 總線的 usb_device_match。返回 1 表示匹配成功。probe,否則調用驅動自身的 drv->probe。此階段驅動可進一步驗證設備是否真正受控。driver_bound,將設備的 knode_driver 加入驅動的 klist_devices,發送 BUS_NOTIFY_BOUND_DRIVER 通知。dev->driver = NULL。整個匹配過程使用信號量(dev->sem、dev->parent->sem)保護設備狀態,防止並發探測導致競態。
Linux 驅動模型通過「總線-驅動-設備」三層架構,實現了設備的自動發現與驅動綁定。driver_attach 作為入口,配合 klist 安全遍歷、總線匹配回調、分層探測機制,構建了健壯的設備驅動自動化框架。