Ubuntu 网络设备驱动开发指南

网络设备驱动是Linux内核中用于管理网络接口卡(NIC)的驱动程序。以下是Ubuntu环境下网络设备驱动的入门知识和开发要点。

一、网络设备驱动基础概念

1. 网络设备特点

  • 面向数据包(packet)而非字节流

  • 无缓存机制(直接发送/接收数据包)

  • 支持多种协议(以太网、WiFi等)

2. 与字符/块设备的区别

  • 不显示在/dev目录下

  • 使用套接字(socket)接口而非文件操作

  • 通过ifconfig/ip命令管理

二、最简单的网络设备驱动框架

c
 
复制
 
下载
#include <linux/module.h>
#include <linux/netdevice.h>

#define DRV_NAME "simple_net"
#define DRV_VERSION "1.0"

static struct net_device *simple_dev;

static int simple_open(struct net_device *dev)
{
    printk(KERN_INFO "%s: device opened\n", dev->name);
    netif_start_queue(dev);
    return 0;
}

static int simple_release(struct net_device *dev)
{
    printk(KERN_INFO "%s: device closed\n", dev->name);
    netif_stop_queue(dev);
    return 0;
}

static netdev_tx_t simple_xmit(struct sk_buff *skb, struct net_device *dev)
{
    printk(KERN_INFO "%s: packet transmitted, len=%d\n", dev->name, skb->len);
    dev_kfree_skb(skb);
    return NETDEV_TX_OK;
}

static const struct net_device_ops simple_netdev_ops = {
    .ndo_open = simple_open,
    .ndo_stop = simple_release,
    .ndo_start_xmit = simple_xmit,
};

static void simple_setup(struct net_device *dev)
{
    ether_setup(dev); // 设置以太网默认参数
    dev->netdev_ops = &simple_netdev_ops;
}

static int __init simple_init(void)
{
    int ret;
    
    // 1. 分配网络设备结构
    simple_dev = alloc_netdev(0, DRV_NAME, NET_NAME_UNKNOWN, simple_setup);
    if (!simple_dev)
        return -ENOMEM;
    
    // 2. 注册网络设备
    ret = register_netdev(simple_dev);
    if (ret) {
        printk(KERN_ERR "%s: failed to register\n", DRV_NAME);
        free_netdev(simple_dev);
        return ret;
    }
    
    printk(KERN_INFO "%s: registered as %s\n", DRV_NAME, simple_dev->name);
    return 0;
}

static void __exit simple_exit(void)
{
    unregister_netdev(simple_dev);
    free_netdev(simple_dev);
    printk(KERN_INFO "%s: unregistered\n", DRV_NAME);
}

module_init(simple_init);
module_exit(simple_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple network device driver");
MODULE_VERSION(DRV_VERSION);

三、核心知识点

1. 关键数据结构

net_device结构:

  • 表示一个网络接口

  • 包含硬件信息、操作函数集、统计信息等

  • 通过alloc_netdev()alloc_etherdev()分配

sk_buff结构:

  • 表示网络数据包

  • 包含数据缓冲区、协议头、状态信息等

  • 驱动需要正确处理skb的分配和释放

2. 驱动开发流程

  1. 初始化流程:

    c
     
    复制
     
    下载
    1. 分配net_device (alloc_netdev/alloc_etherdev)
    2. 设置操作函数集 (net_device_ops)
    3. 注册设备 (register_netdev)
  2. 数据包传输:

    • 实现ndo_start_xmit回调函数

    • 处理sk_buff数据包

    • 返回传输状态(NETDEV_TX_OK等)

  3. 数据包接收:

    • 在中断处理中分配skb

    • 填充接收数据

    • 调用netif_rx()napi_gro_receive()

  4. 清理流程:

    c
     
    复制
     
    下载
    1. 注销设备 (unregister_netdev)
    2. 释放资源 (free_netdev)

3. 关键API函数

  • alloc_netdev() - 分配网络设备结构

  • register_netdev() - 注册网络设备

  • netif_start_queue() - 允许数据包传输

  • netif_stop_queue() - 停止数据包传输

  • dev_kfree_skb() - 释放sk_buff

  • netif_rx() - 提交接收到的数据包

四、测试网络设备驱动

1. 加载驱动并检查

bash
 
复制
 
下载
# 加载模块
sudo insmod simple_net.ko

# 查看网络接口
ip link show

# 查看内核日志
dmesg | tail

2. 基本操作测试

bash
 
复制
 
下载
# 启用接口
sudo ip link set simple_net up

# 分配IP地址
sudo ip addr add 192.168.1.100/24 dev simple_net

# 测试ping(需要实现接收处理)
ping -c 3 192.168.1.100

# 禁用接口
sudo ip link set simple_net down

3. 数据包捕获

bash
 
复制
 
下载
# 使用tcpdump监控
sudo tcpdump -i simple_net -n

五、进阶开发方向

  1. NAPI支持:

    • 实现轮询模式接收

    • 提高高负载下的性能

  2. 硬件抽象层:

    • 与实际硬件交互

    • DMA缓冲区管理

  3. 统计信息:

    • 实现get_stats64操作

    • 暴露接口统计信息

  4. 多队列支持:

    • 实现多传输队列

    • 支持RSS(接收端缩放)

  5. 卸载功能:

    • 校验和计算卸载

    • TSO(TCP分段卸载)

六、调试技巧

  1. sysfs调试接口:

    bash
     
    复制
     
    下载
    ls /sys/class/net/simple_net/
    cat /sys/class/net/simple_net/statistics/tx_packets
  2. 动态调试:

    bash
     
    复制
     
    下载
    echo 'file simple_net.c +p' > /sys/kernel/debug/dynamic_debug/control
  3. 内核探测:

    bash
     
    复制
     
    下载
    sudo perf probe --add simple_xmit
    sudo perf stat -e probe:simple_xmit -a sleep 10

七、实际硬件驱动开发要点

  1. PCIe网卡驱动框架:

    c
     
    复制
     
    下载
    static struct pci_driver my_driver = {
        .name = "my_nic",
        .id_table = my_pci_tbl,
        .probe = my_probe,
        .remove = my_remove,
    };
  2. DMA缓冲区管理:

    • 使用dma_alloc_coherent()分配

    • 正确处理缓存一致性

  3. 中断处理:

    • 注册中断处理函数

    • 实现上半部和下半部

  4. 电源管理:

    • 实现suspend/resume回调

    • 处理唤醒事件

通过掌握这些知识点,您可以开发出功能完善的网络设备驱动程序,并根据实际需求实现各种高级功能。

 
 
 
posted @ 2025-06-14 20:28  MaxBruce  阅读(114)  评论(0)    收藏  举报