看完第8章以後再回頭看看第4 5 6 7的一些知識點就非常清楚了本章主要講裝置的註冊 登出 啟用 禁止 註冊
裝置什麼時候註冊
1)載入驅動程式時(靜態編譯進核心的在啟動時註冊,動態模組載入的在載入時註冊)
2)插入熱插拔裝置時(插入時核心通知其裝置驅動註冊該裝置)裝置的註冊實際上是由pci_driver->probe函數執行來完成的(probe何時調用參考前幾章) 流程如:其中alloc_netdev分配記憶體塊(包括net_device結構、驅動程式私人資料區塊以及強制對齊填充資料),
xxx_setup(dev) 初始化net_device結構(僅初始化任何乙太網路卡所共用的欄位和函數指標)
netdev_boot_setup_check 檢查使用者在載入核心時是否提供了參數,
register_netdev(dev)( 註冊中的主要函數 )把新的net_device插入到dev_base中 看;register_netdev流程如因為net_device結構的改變受rtnl_lock rtnl_unlock兩個鎖保護,所以register_netdev函數在開始時獲得鎖,在返回前釋放鎖,一旦register_netdevice完成了它的工作,便會調用net_set_todo把新的net_device添加到net_todo_list中,這個list包含了註冊已結束的裝置。最後rtnl_unlock不僅釋放鎖,而且還調用netdev_run_todo函數,後者掃描net_todo_list完成註冊。
register_netdevice執行如下操作:
1)net_device部分域初始化
2)allow_divert_blk函數分配特性需要的配置塊,並串連到dev->divert
3) 執行驅動自訂的初始化函數
4) dev_new_index函數分配唯一識別碼
5) 把net_device加到全域鏈表dev_base中,並將其插入dev_name_base和dev_index_head兩個雜湊表中(用於尋找)
6) 檢測特性標誌是否有效
7) 設定 dev->state中的__link_state_present標誌
8)初始化隊列規則、流量控制
9)netdev_chain通知鏈通知所有對裝置感興趣的子系統
10)調用netdev_run_todo 更新dev->reg_state 並在sysfs檔案系統中註冊該裝置 登出
裝置什麼時候登出
1)卸載驅動程式
2)移除熱插拔裝置
裝置的登出是由pci_driver->remove函數執行的,流程如;unregister_netdevice執行如下操作;
1)若裝置此時沒有被禁止,則調用dev_close禁止它
2)從dev_base中刪除net_device結構,同時也從兩個雜湊表中刪除該裝置
3)調用dev_shutdown函數釋放所有與裝置相關的隊列規則執行個體
4)發送netdev_unregister通知到netdev_chain通知鏈使其他核心組件知道登出事件發生
5)釋放所有連結到net_device結構的資料區塊
6)最後調用net_set_todo,dev_put函數減少引用計數。調用net_run_todo函數從sysfs中登出裝置,並設定dev->state為netreg_unregistered,等到所有的引用都釋放後,調用dev->destructor結束登出過程
enable,disable網路裝置
enable
網路裝置註冊完後必須enable後才能收發資料(其他裝置也一樣,這裡以網路裝置為例)
首先調用dev->open處理裝置enable請求,設定dev->state的__link_state_start標誌位,標記裝置開啟並在運行,設定dev->flags的iff_up標誌位標記裝置啟動。
調用dev_activate所指函數 初始化流量控制用的排隊規則,並啟動監視定時器。
發送netdev_up通知給netdev_chain通知鏈以通知對裝置enable感興趣的核心組件 disable
在裝置登出時,首先調用dev_close禁止該網路裝置
發送netdev_going_down通知到netdev_chain通知鏈以通知對裝置禁止有興趣的核心組件
調用dev_deactivate函數禁止出口隊列規則,確保裝置不再用於傳輸,並停止監視定時器
清除dev->state的__link_state_start
若已調度了輪詢讀裝置入隊列資料包,則等待此動作完成
清除dev->flags的iff_up
發送netdev_down通知給netdev_chain通知鏈,通知對裝置禁止感興趣的核心組件