LINUX内核网卡驱动解析
传输控制协议 TCP:为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用 程序。 用户数据报协议 UDP:提供了无连接通信,且不对传送包进行可靠的保证。 适合于一次传输小量数据,可靠性则由应用 层来负责。 应用层 应用程序通过这一层访问网络。 网络接口技术 IP 使用网络设备接口规范 NDIS 向网络接口层提交帧。IP 支持广域网和本地网接口技术。 串行线路协议 TCP/IPG 一般通过 internet 串行线路协议 SLIP 或点对点协议 PPP 在串行线上进行数据传送。 BSD Socket 接口是个通用的接口,它支持各种网络工作形式。一个套接字描述一个通讯连接的一端,两个通讯程序中 各自有一个套接字来描述它们自己那一端。Linux 支持多种类型的套接字。每一类型的套接字有它自己的通信寻址方法 。 Linux 支持下列套接字地址族或域: UNIX Unix 域套接字 INET Internet 地址族支持通过 TCP/IP 协议的通信 AX25 Amateur radio X25 IPX Novell IPX APPLETALK Appletalk DDP X25 X25 INET socket 层支持包括 TCP/IP 协议在内的 internet 地址族。这些协议是分层的,一个协议使用另一个协议的服务。它 与 BSD socket 层的接口要通过一系列 Internet 地址族 socket 操作,这一操作是在网络初始化时就已经注册到 BSD socket 层的。为了不把 BSD socket 与 TCP/IP 的特定信息搞混, INET socket 层使用它自己的数据结构 sock ,它与 BSD socket 结构相连。
__kernel_size_t iov_len; //数据长度 };
socket 结构 Linux 应用层的程序使用的是 标准 的 BSD Socket 接口, BSD Socket 层管理多种地址 簇 。 socket 结构是 BSD Socket 层的 socket 控制结构,在应用程序中通过使用一个 socket 文件描述符与一个 socket 相对应。 include/linux/net.h struct socket { socket_state unsigned long struct proto_ops state; //socket 状态 flags;//如 SOCK_ASYNC_NOSPACE 的标识 *ops;//协议特定的 socket 操作
int int struct socket struct sock struct scm_cookie struct msghdr struct iovec struct kiocb };
flags; size; *sock; *sk; *scm; *msg, async_msg; async_iov; *kiocb;
unsigned int
len,//实际的数据长度 data_len,//数据长度 mac_len,//链路层头的长度 csum;//校验结构
在内核中的 BSD Socket 层使用 msghdr 结构来存储数据包,使用 socket 结构来字处理控制 socket。在 INET Socket 以 下层中使用 sk_buff 结构来存储数据包。使用 sock 结构来管理数据包存放和调度。下面这两个结构分别进行讨论。 msghdr 结构 linux/socket.h struct msghdr { void int struct iovec * * msg_name; msg_namelen; msg_iov; // Socket 名字 //名字长度 //数据块 //数据块个数 //各个协议的 magic (如 BSD 文件描述子
struct icmphdr struct igmphdr struct iphdr struct ipv6hdr unsigned char } h;
*icmph; *igmph; *ipiph; *ipv6h; *raw; //
union { struct iphdr struct ipv6hdr struct arphdr unsigned char } nh; *iph; //IP 层头 *ipv6h; *arph; *raw;
__u32 spinlock_t }; struct sk_buff {
qlen; //链表节点的个数 lock;
/* These two members must be first. */ struct sk_buff struct sk_buff *next; *prev;
struct sk_buff_head struct sock struct timeval struct net_device struct net_device struct net_device
socket 结构中的 state 状态值如下枚举结构,主要的有 SS_UNCONNECTED 和 SS_CONNECTED ,这个结构列出如 下 typedef enum { SS_FREE = 0, SS_UNCONNECTED, SS_CONNECTING, SS_CONNECTED, SS_DISCONNECTING } socket_state; //不允许的状态 //没连接到任何 socket //在连接中 //已连接到 socket //连接正在断开中
*list;//表示在哪个链表上 *sk; //被哪个 socket 拥有 stamp;//数据包到达的时间 *dev; //数据包经过的网络设备 *input_dev;//数据包到达的设备 *real_dev; //数据包正在使用的设备
union { struct tcphdr struct udphdr *th; //TCP 传输层头 *uh; //UDP 头
图 socket 在文件系统 inode 中的位置 sk_buff 结构及管理 sk_buff 结构 Linux 网络层采用统一的缓冲区结构 skbuff,一个个单独的 skbuff 被组织成双向链表的形式。网卡接收到数据帧后,系 统内核为接收到的数据帧放在 skbuff 结构管理的缓冲区内。在网络协议处理的时候 , 数据均以 skbuff 的形式在各层之间 传递、处理。 sk_buff 提供了众多指针 ,可以快速的定位协议头位置,它同时保留了许多数据包信息 (如使用的网络设备等 ),以便协议层 根据需要灵活应用。 下面套接字缓冲区流程图说明了 sk_buff 流动的过程。在源主机上,INET socket 层创建了 sk_buff 缓冲区,它沿网络自 上而下传递,它先在协议层流动,最后在物理层消失。同时把它所带的数据传递给目标主机的物理层的套接字缓冲区, 该缓冲区自下而上传递到目标主机的套接字,并把数据传递给用户进程,目标主机的套接字缓冲区也同时消失。当套接 字缓冲区在协议层流动过程中,每个协议都在发送数据区添加自己的协议头和协议尾,而在接收数据时去掉这些协议 头和协议尾。设置 sk_buff 数据结构的主要目的就是为网络提供一种统一有效的缓冲区操作方法。
struct fasync_struct *fasync_list;//异步唤醒队列 struct file struct sock wait_queue_head_t short unsigned char PF_LOCAL� }; *file;//回指向 file 的指针 *sk;//指向下一层协议中的 sock 结构 wait;//等待在这个 socket 上的任务列表 type; //数据包的类型 passcred;// credentials (used only in Unix Sockets (aka
Linux 网络层次图
2 数据包结构 结构 sock_iocb 是 socket 的 I/O 控制块,用来进行 socket 的 I/O 异步处理,它是网络传输的一个 总的控制结构,结构 sock_iocb 列出如下(在 include/net/sock.h 中): struct sock_iocb { struct list_head list;
__kernel_size_t msg_iovlen; void * msg_control;
__kernel_size_t msg_controllen; /* Length of cmsg list */ unsigned }; msg_flags; //保存接收数据的时候使用的控制标志
linux/uio.h struct iovec { void __user *iov_base; //数据缓存区地址
Linux 系统调用建立新的套接字时,需要传递套接字的地址族标识符、 套接字类型以及协议。 内核套接字分配新的 socket 数据结构。Socket 数据结构实际是 VFS 索引节点数据结构的一部分,分配新的 socket 数据结构实际就是分配新的 VFS 索引节点。socket 在文件系统位置如下图所示:
• 4.2.1 接收例程 • 4.2.2 发送例程 4.3 网络核心层 • • 4.3.1 net_device 结构 • 4.3.2 网络设备初始化 • 4.3.3 接收数据包 • 4.3.4 包接收 • 5 网卡驱动程序 • 5.1 NAPI • 5.2 8139CP 网卡驱动程序
1 Linux 网络系统分层结构 Linux 网络系统遵守一个四层的模型概念:应用层、 传输层、 互联层和网络接口层。 模型的基层是网络接口层。 负责数据帧 的发送和接收,帧是独立的网络信息传输单元。网络接口层将帧放在网上,或从网上把帧取下来。互联协议将数据包封 装成 internet 数据报,并运行必要的路由算法。 这里有四个互联协议: 网际协议 IP:负责在主机和网络之间寻址和路由数据包。 地址解析协议 ARP:获得同一物理网络中的硬件主机地址。 网际控制消息协议 ICMP:发送消息,并报告有关数据包的传送错误。 互联组管理协议 IGMP:被 IP 主机拿来向本地多路广播路由器报告主机组成员。 传输协议在计算机之间提供通信会话。传输协议的选择根据数据传输方式而定。 两个传输协议: