1.概述
Linux系统多用于服务器上,Linux非常牢固的支持网络。在Linux,网络分为两个层,分别是网络堆栈协议支持层,以及接收和发送网络协议的设备驱动程序层。网络堆栈是硬件中独立出来的部分,主要用来支持TCP/IP等多种协议,而网络设备驱动层是连接网络堆栈协议层和网络硬件的中间层。
网络设备驱动程序的主要功能是:
(1)模块加载或内核启动相关的初始化处理
(2)清除模块时的处理
(3)网络设备的检索和探测
(4)网络设备的初始化和注册
(5)打开或关闭网络设备
(6)发送网络数据
(7)接收网络数据
(8)中断处理(在发送完数据时,硬件向内核产生一个中断,告诉内核数据已经发送完毕,在网络设备接收到数据时,也要发生一个中断,告诉内核,数据已经到达,请及时处理)
(9)超时处理
(10)多播处理
(11)网络设备的控制ioctl
而Linux网络设备驱动的主要功能就是网络设备的初始化,网络设备的配置,数据包的收发。
2. Linux网络设备驱动的接口函数
net_device结构体存储一个网络接口的重要信息,它是系统中网络设备的代表。
sk_buff是socket buffer,在网络传输过程中起着重要的作用,内核把数据包封装成socket buffer向网络硬件发送,当网络硬件接收到数据包时,再把数据包封装成socket buffer向内核传送。
注册网络设备:
int register_netdev(struct net_device *dev);//网络设备与字符设备,块设备不同,没有主,次设备号
注销网络设备:
void unregister_netdev(struct net_device *dev);
返回网络设备结构体的private data:
void *netdev_priv(struct net_device *dev);
即返回我们定义的设备结构体。
保存设备统计信息的结构体
struct net_device_stats
打开发送队列,能够发送数据包,在open()中调用
netif_start_queue(struct net_device *dev);
关闭发送队列,在stop()中调用
netif_stop_queue(struct net_device* dev);
重新打开队列,一般在关闭队列之后重启队列
netif_wake_queue(struct net_device *dev);
当数据到达时,通知内核数据包到达
void netif_rx(struct sk_buff *skb);
分配一个sk_buff结构体
struct sk_buff *dev_alloc_skb(unsigned int len);
释放sk_buff结构体
void dev_kfree_skb(struct sk_buff *skb);
从数据的尾部扩展len长度的空间,为了把数据放到skb的尾部
unsigned char* skb_put(struct sk_buff *skb,int len);
SIOCDEVPRIVATE 可用ioctl执行的16个命令的第一个命令
最后一个是SIOCDEVPRIVATE+15
3.下面给出一个虚拟硬件的网络驱动的例子
#undef PDEBUG /* undef it, just in case */
#ifdef SNULL_DEBUG
# ifdef __KERNEL__
/* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "snull: " fmt, ## args)
# else
/* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif
#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */
/* These are the flags in the statusword */
#define SNULL_RX_INTR 0x0001
#define SNULL_TX_INTR 0x0002
/* Default timeout period */
#define SNULL_TIMEOUT 6 /* In jiffies */
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/interrupt.h> /* mark_bh */
#include <linux/in.h>
#include <linux/netdevice.h> /* struct device, and other headers */
#include <linux/etherdevice.h> /* eth_type_trans */