Linux 網卡驅動是協議棧與硬件的橋樑。本文以 Intel e100 驅動為例,系統梳理驅動模組載入、PCI 探測、net_device 分配初始化、NAPI 接入以及 DMA/IO 內存映射準備的完整流程。
static int __init e100_init_module(void)
{
if (debug 条件) printk(KERN_INFO "驅動版本信息");
return pci_module_init(&e100_driver); // 註冊 PCI 驅動
}
pci_module_init 將 e100_driver 註冊到 PCI 子系統,當總線掃描到匹配設備時觸發 probe。
static struct pci_driver e100_driver = {
.name = DRV_NAME,
.id_table = e100_id_table, // 支援的設備 ID 列表
.probe = e100_probe, // 設備探測/初始化
.remove = __devexit_p(e100_remove),
#ifdef CONFIG_PM
.suspend = e100_suspend,
.resume = e100_resume,
#endif
};
此函數完成從 PCI 設備到網路設備的完整轉化:
if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
printk(KERN_ERR "Etherdev alloc failed");
return -ENOMEM;
}
alloc_etherdev 內部調用 alloc_netdev,預分配私有數據區 sizeof(struct nic),並預設以太網相關字段(dev_addr、broadcast 等)。
netdev->open = e100_open;
netdev->stop = e100_close;
netdev->hard_start_xmit = e100_xmit_frame; // 發送入口
netdev->get_stats = e100_get_stats;
netdev->set_multicast_list = e100_set_multicast_list;
netdev->set_mac_address = e100_set_mac_address;
netdev->change_mtu = e100_change_mtu;
netdev->do_ioctl = e100_do_ioctl;
SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
netdev->tx_timeout = e100_tx_timeout;
netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
// NAPI 關鍵接口
netdev->poll = e100_poll; // 輪詢處理函數
netdev->weight = E100_NAPI_WEIGHT; // 輪詢權重
#ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = e100_netpoll; // Netpoll 專用輪詢
#endif
nic = netdev_priv(netdev);
nic->netdev = netdev;
nic->pdev = pdev;
nic->msg_enable = (1 << debug) - 1;
pci_set_drvdata(pdev, netdev); // PCI 核心關聯 netdev
if ((err = pci_enable_device(pdev))) {
DPRINTK(PROBE, ERR, "Cannot enable PCI device");
goto err_pci;
}
// 後續:pci_set_master(pdev) 設置總線主模式
// pci_request_regions(pdev) 申請 IO/內存資源
// ioremap 映射寄存器地址空間
| 接口 | 函數 | 觸發場景 |
|---|---|---|
open | e100_open | ifconfig eth0 up、ip link set dev eth0 up |
stop | e100_close | 接口關閉 |
hard_start_xmit | e100_xmit_frame | 協議棧發送數據包 |
poll | e100_poll | NAPI 輪詢(接收/發送清理) |
tx_timeout | e100_tx_timeout | 發送超時看門狗 |
set_mac_address | e100_set_mac_address | 修改 MAC 地址 |
ioctl | e100_do_ioctl | ethtool、SIOCGMIIPHY 等 |
pci_enable_device 分配 IRQ、IO/內存 BAR 空間pci_set_master 允許設備發起 DMA 事務pci_request_regions 鎖定 BAR 區域ioremap 將 BAR 物理地址映射為核心虛擬地址request_irq 註冊 e100_intr,啟用 MSIX/MSI 或傳統中斷e100 通過實現 poll 接口並設置 weight,接入核心 NAPI 框架:
netif_rx_schedule 調度,不處理具體數據net_rx_action 軟中斷中調用 pollbudget 機制限制單次輪詢處理量,保證公平調度e100 驅動的 probe 流程展示了標準 Linux 網卡驅動的完整骨架:PCI 子系統綁定 → net_device 分配與操作函數綁定 → 私有數據初始化 → 硬件資源獲取與映射 → NAPI 接入。這一模式被絕大多數現代網卡驅動遵循,是驅動開發的標準範式。
Linux 網路程式設計兩大經典錯誤:ENOTSOCK 與 ECONNREFUSED 成因與修正
VPS 部署 OpenVPN 完整實戰指南 (Debian/Ubuntu 一鍵腳本與手動配置雙軌)
免分區安裝 Ubuntu:Wubi 在 Windows 環境下的輕鬆部署指南
解決 ARM 開發板運行程序提示 Illegal Instruction 錯誤
Verilog HDL 關鍵字全景圖:模組結構、過程塊、數據類型與賦值語義精講
CentOS 6.x 卸載系統預裝 OpenJDK (gcj) 標準化操作指南
Linux 服務器「ping: unknown host」域名解析故障排查全流程:從 resolv.conf 到 nsswitch.conf