NetDevice
在 Linux 内核中,net_device 数据结构用来代表网络设备,包含设备的硬件和软件配置信息,是网络驱动层最核心的数据结构。
结构体解析
通用字段
设备名称、next 指针指向下一个 net_device、设备状态 state、网络设备索引值 ifindex(用来标志网络设备以便快速定位,设备被创建后由 dev_get_index 函数分配)、refcnt 表示网络设备的引用次数。
|
|
硬件信息
内存共享字段(描述网络适配器与内核共享的内存空间,指定发送包和接受包所在的区域)、I/O 基地址(用于驱动程序搜索设备)、设备使用的中断号 irq、分配给设备的 DMA 通道号、多端口设备使用的不同端口 if_port(网络介质类型决定)。
|
|
物理层数据字段
指定 2 层协议头部长度、最大传输单元 mtu(以太网 1500byte)、网络设备输出队列的最大长度、网络设备类型 type、地址字段(广播地址、多播地址表等)
|
|
设备方法
|
|
网络设备的创建和注册
一个网络设备被使用前,需要先被创建成为一个 struct net_device 并注册。下面描述注册过程:
和其他所有内核数据结构一样,net_device 包含了一个 kobject 和引用计数,并且通过 sysfs 导出信息。由于与其他结构相关,因此它必须被动态分配。用来执行分配的内核函数是 alloc_netdev,其原型如下:
|
|
函数参数定义如下:
sizeof_priv是驱动程序的私有数据区的大小,这个区成员和net_device结构一同分配给网络设备。name是接口的名字,在用户空间可见,可以使用类似printf中%d的格式setup是一个初始化函数,用来设置net_device结构剩余的部分
使用示例如下,注意必须要检查函数返回值,以确定分配工作完成:
|
|
网络子系统针对 alloc_netdev 函数,为不同种类的接口封装了许多函数,最常用的是 alloc_etherdev:
|
|
该函数使用 eth%d 的形式指定分配给网络设备的名字,它提供了自己的初始化函数 ether_setup,用正确的值为以太网设备设置 net_device 中的许多成员。因此在驱动程序中没有为 alloc_etherdev 提供初始化函数。
一旦 net_device 结构体被初始化后,剩余的工作就是将该结构体传递给 register_netdev 函数:
|
|
网络设备的开启与关闭
net/core/dev.c
开启网络设备函数 dev_open(struct net_device *dev)。如果网络设备已经激活或者它尚未被注册,函数返回错误信息。
- 判断设备是否激活;
- 使用 set_bit 函数修改设备状态为**__LINK_STATE_START**,调用 net_device 中的 open 指向函数设置该设备;
- 激活网络设备的队列和调度器;
- 将事件(NETDEV_UP)登记到通知链:notifier_call_chain(&netdev_chain,事件,dev)。
关闭网络设备函数 dev_close(struct net_device *dev)。
- 如果网络设备未被激活,则不需要关闭;
- 将事件(NETDEV_GOING_DOWN)登记到通知链:notifier_call_chain(&netdev_chain,事件名,dev);
- 删除包调度器中的相应信息:dev_deactivate;
- 清除设备的活动状态:clear_bit;
- 调用 net_device 中的 stop 指向函数,执行停止操作。
参考资料
- Understanding Linux Kernel Internals:Part II
-
No backlinks found.