linux内核-网络数据包传送通道解析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

网络栈自下而上的数据包传输通道具体如下:

(1):硬件监听物理传输介质,进行数据的接收,当完全接收一个数据包后,产生中断(这个过程完全由网络设备硬件负责)。

(2):中断产生后,系统调用驱动程序注册的中断处理程序进行数据接收,一般在接收例程中,完成数据从硬件缓冲区到内核缓冲区的复制,将其封装为内核特定结构(sk_buff结构),最后调用链路层提供的借口函数netif_rx,将数据包由驱动层传递给链路层。

(3):在netif_tx中,为了减少中断执行时间(netif_rx函数一般在驱动层中断例程中被调用),该函数将数据包暂存在链路层维护的一个数据包队列中(具体的由backlog变量指向),并启动专门进行网络处理的下半部分对backlog队列中数据包进行处理。

(4):网络下半部分执行函数net_bh,从backlog队列中取数据包,在进行完本层相关处理后,遍历ptype_base指向的网络层协议(由packet_type结构表示)队列,进行协议号的匹配,找到协议号匹配的packet_type结构,调用结构中的接收函数,完成数据包从链路层到网络层的传递。对于ARP协议,那么调用的是arp_rev函数,IP协议则是ip_rcv函数。

(5):假设数据包使用的时IP协议,那么从链路层传递到网络层时,将进入ip_rcv 总入口函数,ip_rcv完成本层的处理后,以本层首部(IP首部)中标识的传输层协议号为散列值,对inet_protos散列表进行匹配查询,以寻找到合适的inet_protocol结构,进而调用结构中接收函数,完成数据包从网络层到传输层的传递对于UDP协议,调用udp_rcv函数,TCP协议调用tcp_rcv函数,ICMP 协议调用icmp_rcv函数,IGMP协议调用igmp_rcv函数。ICMP ,IGMP是网络层协议,但其都是封装在IP协议中,所以当做传输层看待。

(6):假如数据包使用的时TCP传输层协议,那么此时将进入tcp_rcv函数。TCP 协议的套接字对应sock结构都被挂入tcp_prot 全局变量表示的proto结构之sock_array数组中,采用以本地端口号为索引的插入方式,所以当tcp_rec函数接收到一个数据包,在完成必要的检查和处理后,其将以TCP首部中得目的端口号(对一个接收的数据包而言,其目的端口号就是本地所使用的端口号)为索引,在tcp_prot对应sock结构之sock_array数组中得到正确的sock结构队列,再辅之以其他条件遍历该队列进行对应的sock结构的查询,在得到匹配的sock结构后,将数据包挂入该sock结构的缓存队列中(由sock结构中receive_queue字段指向),从而完成数据包的最终接收。

数据包发送通道是如何创建的:

即是上层向下层提供发送接口函数共下层直接进行调用,入驱动层通过device结构hard_start_xmit函数指针向链路层提供发送函数,链路层提供dev_queue_xmit发送函数供网络层调用,而网络层提供ip_queue_xmit函数供传输层调用。

基于TCP协议的数据包

从应用层调用write函数开始,先经历sock_write(net/socket.c)、inet_write (net/inet/af_inet.c)和tcp_write( net/inet/tcp.c ),只有到达tcp_write函数时,才进行数据的真正处理,sock_write,inet_write只是进行简单的检查处理。(只有在传输层才能进行数据的封装,才知道需要预留多大的内核空间创建一个数据帧)。

对于七层分层方式,在表示层所进行的加密等操作此处没有讨论,本版本网络栈实现是针对四层模型。

(1)tcp_write函数完成数据帧的封装。将数据从用户缓冲区复制到内核缓冲区,并封装在sk_buff结构中,根据网络的拥塞情况:(1)不经过sock结构之write_queue队列直接被发送出去,(2)数据包被暂时缓存在write_queue队列中,稍后发送。其后调用ip_queue_xmit函数将数据包发往下层——网络层处理。

(2)ip_queue_xmit函数继续对数据帧进行完善后,调用dev_queue_xmit 函数将数据包送往链路层进行处理,同时将数据包缓存与sock结构之send_head 队列。这个缓存的目的在于TCP协议需要保证可靠性数据传输,防止数据包丢失,一旦发生丢失,就需要重新发送send_head队列的数据包。

数据包不会同时存在于write_queue和send_head中,数据包传给dev_queue_xmit后,就从write_queue队列中删除。

(3)dev_queue_xmit函数完成其本层的处理后,调用发送设备device 结构之hard_start_xmit指针指向的具体硬件数据数据发送函数。

linux内核网络协议栈代码分析

一.linux内核网络栈代码的准备知识

1. linux内核ipv4网络部分分层结构:

BSD socket层:这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一部分的文件

主要有:/net/socket.c /net/protocols.c etc

INET socket层:BSD socket是个可以用于各种网络协议的接口,而当用于

tcp/ip,即建立了AF_INET形式的socket时,

还需要保留些额外的参数,于是就有了struct sock结构。文件主要

有:/net/ipv4/protocol.c /net/ipv4/af_inet.c /net/core/sock.c etc

TCP/UDP层:处理传输层的操作,传输层用struct inet_protocol和struct proto 两个结构表示。文件主要

有:/net/ipv4/udp.c /net/ipv4/datagram.c /net/ipv4/tcp.c

/net/ipv4/tcp_input.c /net/ipv4//tcp_output.c

/net/ipv4/tcp_minisocks.c

/net/ipv4/tcp_output.c /net/ipv4/tcp_timer.c

相关文档
最新文档