TCP/IP协议栈在Linux与FreeBSD中的实现分析5

Linux开发之初并没有网络功能,因此在内核对于网络的支持上与FreeBSD相比仍然有一定的差距。图2TCP协议栈在Linux上的实现。

2 TCP协议栈在Linux上的实现

 

TCP协议在LINUX上的实现稍显复杂。首先从发送数据开始分析。在LINUX上,socket被实现为一个文件系统,这样可以通过vfswrite来调用,也可以直接使用send来调用,它们最终都是调用sock-sendmsgsock-sendmsg通过它的内核版本sock-sendmsg直接调用tcp-sendmsg来发送数据。在tcp-sendmsg中,同时完成数据复制和数据校验,节省了一次遍历操作,这是和FreeBSD不同的地方。Linux使用skb结构来管理数据缓冲,这与FreeBSDm-buf大同小异。当复制完数据后,使用tcp-push来进行发送。Tcp-push过-tcppushpendingframes调用tcpwritexmit数据填入top的发送缓冲区。这里的填充仅是指针引用而已。下一步,tcp-transmit-skb将数据放人ip的发送队列。Ipqueuexmit函数完成IP包头的设置以及数据效验,并调用ip-output进入下一步发送。如果不用分片,将使用ipfinishoutput继续发送。在这里,将检查硬件头部描述符(这里就是以太网包头)并填充人数据缓冲区,而后调用devqueuexmit函数来进一步处理。Dev-queue-xmit函数将数据排队放人硬件缓冲区以等待随后的发送。而使用具体的网卡驱动程序cp-start-xmit 来完成数据的最终发送。最后的cp-start-xmit做的事情和freebsd的相应函数差不多,检查数据,并将其复制进硬件级冲。

当接收到一个数据包的时候,网卡会产生中断,这样网卡驱动的cp-interrupt会被调用。Cp-interrupt做的事情很省,只进行必要的检查后就返回了,更多的事情通过cp-rx-poll来完成,这是因为linux驱动分为上半部和下半部,下半部的cp-rx-poll函数在软中断中被调用,这样做是为了提高驱动的处理效率。Cprxpoll做的事情主要就是把申请并将数据复制进一个skb缓冲中。Netif-rx函数将数据从这个队列中转移至网络核心层队列中,netif-receive-skb从这里接收数据,并调用ip-rcv来处理。Ip-rcvip-vcv-finish一起检查数据包,得到包的路由,并调用相应的input函数来完成路由,在这里就是ip-rcv-finish一起检查数据包,得到包的路由,并调用相应的input函数来完成路由-在这里就是ip-local-deliverip-local-deliver完成IP包的重组,而后将使用ip-local-deliver-finish来进入TCP的处理流程,tcp-v4-do-rcv先判断是否正常的用户数据,如果是则用

tcp-rcv-cstabUshde处理,否则用tcprcv-state-process来更新本条TCP连接的状态机。在top-rcv-cstablished中同样实现有首部预测。如果一切顺利,将唤醒等待在top-recvmsg中的用户进程。后者将数据从skb缓冲中复制进用户进程缓冲。

 

你可能感兴趣的:(TCP/IP协议栈在Linux与FreeBSD中的实现分析5)