1.Linux网络子系统
系统调用接口层
为应用程序提供访问网络子系统的统一方法。
协议无关层
提供通用的方法来使用传输层协议。
协议栈的实现
实现具体的网络协议
设备无关层
协议与设备驱动之前通信的通用接口
设备驱动程序
2.重要数据结构
2.1 网卡描述结构
在Linux内核中,每个网卡都由一个net_device结构来描述,其中的一些重要成员有:
char name[IFNAMSIZ]
设备名,如:eth%d
unsigned long base_addr
I/O 基地址
const struct net_device_ops *netdev_ops;
记录了网卡所支持的操作
2.2 网卡操作集合
类似于字符设备驱动中的file_operations结构,net_device_ops结构记录了网卡所支持的操作。
static 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,
};
2.3 网络数据包
Linux内核中的每个网络数据包都由一个套接字缓冲区结构 struct sk_buff 描述,即一个sk_buff结构就是一个网络包,指向sk_buff的指针通常被称做skb。
3.网卡驱动架构分析
cs89x0.c:
/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0
* driver for linux.
*/
static const struct net_device_ops net_ops = { //net_device_ops结构,各种网卡操作函数接口
.ndo_open= net_open,
.ndo_stop= net_close,
.ndo_tx_timeout= net_timeout,
.ndo_start_xmit = net_send_packet,
.ndo_get_stats= net_get_stats,
.ndo_set_multicast_list = set_multicast_list,
.ndo_set_mac_address = set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller= net_poll_controller,
#endif
.ndo_change_mtu= eth_change_mtu,
.ndo_validate_addr= eth_validate_addr,
};
static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev) //网卡的发送函数
{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
if (net_debug > 3) {
printk("%s: sent %d byte packet of type %xn",
dev->name, skb->len,
(skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
}
/* keep the upload from being interrupted, since we
ask the chip to start transmitting before the
whole packet has been completely uploaded. */
spin_lock_irqsave(&lp->lock, flags);