1、网络子系统(如下的内核空间的几层)
用户空间 应用层
内核空间 系统调用 通过socket访问网络子系统
内核空间 协议无关接口 一组通用函数通过socket访问不同协议
内核空间 网络协议层 各种传输层网络层协议tcp udp ip
内核空间 设备无关接口
内核空间 设备驱动
硬件设备
2、网卡驱动
设备描述:
每个网络接口都由一个net_device结构来描述,可使用如下内核函数动态分配
struct net_device *alloc_netdev(int sizeof_priv, constr char *mast设备名, void (*setup)(struct net_device *))
struct net_device *alloc_etherdev(int sizeof_priv)
这两个函数有什么关系呢?
struct net_device
{char name[IFNAMESIZ] 设备名,如eth%d "%"表示这个数字由动态的分配编号,以防号冲突
unsigned long state 设备状态
unsigned long base_addr i/o基地址
unsigned int irq 中断号
int (*init)(struct net_device *dev) 在register_netdev时被调用来完成对net_device结构的初始化
int (*open)(struct net_device *dev) 打开接口,ifconfig激活时,接口将被打开
int (*stop)(sturct net_device *dev)
int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev) 数据发送函数
int (*do_ioctl)...
int (*set_mac_address)... 改变硬件地址 需要硬件支持该功能
}
设备描述:
int register_netdev(struct net_device *dev)
注册方式与字符驱动不同之处在于它没有主次设备号,它不是通过设备文件方问,能过socket来问问;
struct sk_buffer{
struct device *dev; 处理该包的设备
__u32 saddr; ip源地址
__u32 saddr; ip上的地址
__u32 raddr; ip路由器地址
__unsigned char *head 分配空间的开始
__unsigned char *data 有效数据的开始
__unsigned char *tail 有效数据的结束
__unsigned char *end 分配空间的结束
unsigned long len; 有效数据的长度
}
它描述一个网络数据包。
skb操作函数
struct sk_buff *alloc_skb(unsigned int len , int priority)
分配一个sk_buff结构,供协议栈代码使用
struct sk_buff *dev_alloc_skb(unsigned int len)
分配一个sk_buff结构,供驱动代码使用,形成一个skb结构,交给上层协议去处理
unsigned char *skb_push(struct sk_buff *skb, int len)
向后移动skb的tail指针,并返回tail移动之前的值;用于先有协议头的情况下向后填充数据;返回移动之前的地址是用于从那里开始填数据;
unsigned char *skb_put(struct sk_buff *skb, int len)
向前移动skb的head指针,并返回head移动之后的值;用于先有数据的情况下在前边加协议头;
kfree_skb(struct sk_buff *skb)
释放一个sk_buff结构,供协议栈代码使用
dev_dfree_skb(struct sk_buff *skb)
释放一个sk_buff结构,供驱动代码使用
网卡驱动
设备打开
open请求任何它需要的系统资源并且启动接口:
1、注册中断,DMA等(一般的字符驱动模块加载的时候就注册中断,因为它们会一直使用)
2、设置寄存器,启动设备
3、启动发送队列,
数据发送
当核心需发送一个数据包时,它调用hard_start_transmit函数,该函数根据io,路由等规则找到处理该包的网卡,将最终调用到该网卡的net_device结构中的hard_start_xmint函数
数据接收
中断方式,当包到达网卡后,它会产生一个接收中断,接着在包的处理程序中进行包的接收工作,如下三步:
1、分配skb skb=dev_alloc_skb(pkt-datalen+2)
2、从硬件中读取数据到skb
3、调用netif_rx(skb)将数据交给协议栈