kernel中使用net_device结构来描述网络设备,这个结构是网络驱动及接口层中最重要的结构。该结构不仅描述了接口方面的信息,还包括硬件信息,致使该结构很大很复杂。通过这个结构,内核在底层的网络驱动和网络层之间构建了一个网络接口核心层(这个叫法引自《TCP迁移报告》),这个中间层类似于文件子系统的VFS。这样底层的驱动程序就不需要过多地关注上层的网络协议,只需要通过内核提供的网络接口核心层就可以很方便将和网络层进行数据的交互。而网络层在向下发送数据时,只需要通过内核提供的这个中间层进行交互即可,不需要关心底层究竟是什么类型的网卡。
1、注册网络设备
网络设备通常在内核启动时或者插拔网络设备时注册,由网络设备驱动负责。网络设备驱动会首先根据自己的网卡类型调用相应的分配net_device结构的函数(例如以太网网卡可以调用alloc_etherdev(),当然也可以直接调用alloc_netdev()),然后初始化网卡相关的成员,最后调用register_netdev()来完成网络设备的注册。每个网络设备在系统中都要有一个唯一的名称,通常以网卡类型的一个缩写为前缀,后面跟着数字,例如,eth1就是一个以太网卡。register_netdev()是对register_netdevice()的包装函数。在调用register_netdev()注册设备时,如果指定的名称中包含%d格式串(只支持%d),内核会选择一个适当的数字来替换格式化串,真正的注册工作由register_netdevice()来完成。
在调用register_netdevice()之前,必须要先调用rtnl_lock()获取rtnl_mutex互斥锁,任何网络配置信息改变时都要首先获取rtnl_mutex互斥锁。注册过程如下所示:
net_device结构的netdev_ops由驱动程序初始化,存储的是设备相关的操作。如果设置了初始化函数,则通过ndo_init成员来进行设备相关的初始化操作
dev_valid_name()用来检查设备名是否为空或者包含不合法的字符(例如‘/’、空白字符),并不会检查名称是否冲突。
dev_new_index()为设备分配一个可用的索引号,用来标识设备,索引号由一个32