TCP协议栈在FreeBSD上的实现
首先介绍FreeBSD上的协议实现,这也是最正统的实现。下图是完整的输入输出路径。
图1 TCP协议栈在FreeBSD上的实现
在图1的左边是TCP/IP的输出,不管应用程序调用哪个输出函数,最终都要调用sosend来完成输出。Sosend将从用户空间把数据复制进内核管理的m-buf数据结构中(m-buf是FreeBSD的TCP实现使用的数据缓冲结构)。在sosend完成数据复制后,将调用TCP的输出函数top-output,它要做的事情是分配一个新的m-buf确信不保存tcp头,并计算相应的数据校验码,在下一步的ip-output中,同样也要进行数据校验工作,并进行数据路由选择最后ether-output并通过if-start来调用具体的硬件驱动程序来完成数据发送。在某个网卡的驱动中,ex-start负责将数据从内棱的m-buf缓冲复制进硬件自己的缓冲区,以完成数据发送工作。在这整个过程中,数据被复制两次,同时也被遍历两次(计算校验码),这是主要的影响效率的地方。
图1右边是TCP/IP的输入,当网卡收到数据时,中断处理程序ex-intr将数据从硬件缓冲复制进m-buf数据结构
中,并调用ether-input来进一步处理。Ether-input通过ether-demux进行分用。如果是一个IP包,将通过软中断调用ip-fastforward进行数据校验,并判断是否要转发,如果失败,用ip-input进行完整的处理。在tcp-input中,进行数据校验和验证后,有一个叫做首部预测算法的优化,可以加快数据处理速度。所有的操作完成后,如果是用户数据,将唤醒用户进程进行处理。同理,用户可以使用多个函数进行数据接收,soreceive负责将数据从m-buf转移至用户进程缓冲。
由以上的分析可以得出。在FreeBSD中,发送和接收数据,所进行的操作差不多,都要进行两次数据复制和两次数据遍历。