[国嵌攻略][133][网卡驱动架构分析]
Linux网络子系统
1.系统调用接口:提供系统调用
2.协议无关接口:统一网络协议给系统调用接口使用
3.网络协议栈 :实现网络协议
4.设备无关接口:统一设备驱动程序给网络协议使用
5.设备驱动程序:实现网卡驱动
Linux驱动在内核中都有一个结构来描述,首先找到设备描述结构,然后找到设备如何注册和初始化。
网卡描述结构
在Linux内核中,每个网卡都由一个net_device结构来描述,其中一些重要成员:
char name[IFNAMSIZ] 设备名,如:eth%d
unsigned long base_addr I/O基地址
const strcut net_device_ops *netdev_ops 网卡操作集合
网卡操作集合
类似于字符设备驱动中的file_operations结构,net_device_ops结构记录了网卡所支持的操作。
struct const struct net_device_ops dm9000_netdev_ops = {
.ndo_open = dm9000_open,
.ndo_stop = dm9000_stop,
.ndo_start_xmit = dm9000_start_xmit,
.ndo_do_ioctl = dm9000_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr
};
网络数据包
Linux内核中每个网络数据包都由一个套接字缓冲区结构struct sk_buff描述,即一个sk_buff结构就是一个网络包,指向sk_buff的指针通常称为skb,例如:struct sk_buff *skb。
struct sk_buff结构内的成员有:head,data,tail,end。head和end是网络包的起始地址和结束地址,data和tail是网络包有效数据的起始位置和结束位置。data和tail的范围不会超过head和end的范围。
网卡驱动架构分析CS8900.c
分析网卡驱动程序时一般分析驱动的初始化,发送和接收。首先要找到模块的入口module_init,但是在早期的Linux驱动程序中模块的入口是init_module。网卡数据的发送函数在net_device_op操作集合中,网卡数据的接收在中断中完成。
网卡初始化
1.分配net_device,使用alloc_etherdev
2.初始化net_device结构
2.1.初始化中断号
2.2.初始化基地址
2.3.初始化MAC地址
2.4.初始化netdev_ops
3.初始化硬件
4.注册网卡驱动,使用register_netdev
网卡数据发送
1.通知上层协议暂停向网卡传送数据,使用netif_stop_queue
2.将skb中的数据写入网卡寄存器发送
3.释放skb空间,使用dev_kfree_sbk
43发送中断处理过程中,通知上层协议,可以再次向网卡传输数据,使用netif_wake_queue
网卡数据接收
1.读取接收状态
2.读取接收的数据长度
3.分配skb结构,使用dev_alloc_skb
4.从网卡寄存器中读出数据,存入skb
5.将收到的数据包skb交给协议栈,使用netif_rx