Kernel Buffer、TCP Socket Buffer和Sliding Window有啥区别

Posted

技术标签:

【中文标题】Kernel Buffer、TCP Socket Buffer和Sliding Window有啥区别【英文标题】:What are the differences between Kernel Buffer, TCP Socket Buffer and Sliding WindowKernel Buffer、TCP Socket Buffer和Sliding Window有什么区别 【发布时间】:2019-05-10 12:46:24 【问题描述】:

这是我对 TCP/IP 中传入数据流的理解

    内核从网络接口将数据读取到其缓冲区 内核将数据从其缓冲区复制到 TCP Socket 缓冲区,滑动窗口在此工作 被 read() 阻塞的程序唤醒并从套接字缓冲区复制数据。

我有点疑惑滑动窗口到底在哪里,还是和socket缓冲区一样

【问题讨论】:

了解到滑动窗口是TCP Socket Buffer的一部分,也就是说滑动窗口的大小永远不能大于TCP Buffer的大小。 【参考方案1】:

Linux 不会将 TCP 的滑动窗口作为一个单独的缓冲区来处理,而是作为几个指示已经接收/读取多少的索引。 Linux内核的包处理过程可以有多种描述方式,随着深入,可以分成小部分,但大体流程如下:

    内核准备通过网络接口接收数据,它准备 SKB(套接字缓冲区)数据结构并将它们映射到接口 Rx DMA 缓冲区环。 当数据包到达时,它们会填充这些预先配置的缓冲区,并在中断上下文中通知内核数据包到达。在这种情况下,缓冲区被移动到网络堆栈的接收队列中,以便在中断上下文之外处理它们。 网络堆栈检索这些数据包并相应地处理它们,最终到达 TCP 层(如果它们确实是 TCP 数据包),后者依次处理窗口。 参见struct tcp_sock 成员u32 rcv_wnd,然后在tp->rcvq_space.space 中将其用作窗口中的每个连接空间。 缓冲区被添加到套接字接收队列中,并作为tcp_recvmsg()中的流数据被相应地读取

这里要记住的重要一点是,副本是性能方面最糟糕的事情。因此,内核将始终(除非绝对必要)将避免复制并使用指针。

【讨论】:

在步骤 2 中通过声明“缓冲区被移动到网络堆栈的 recv 队列”,是否暗示对于网络堆栈,有一个内存区域保存来自套接字缓冲区的数据包? @Knightingale 它不是一个“内存区域”,而是一个指向到达的数据包的链表,并作为消息处理队列链接。

以上是关于Kernel Buffer、TCP Socket Buffer和Sliding Window有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

Linux Kernel TCP/IP Stack — L1 Layer — NIC Controller — Buffer descriptor table

Linux Kernel TCP/IP Stack — Socket Layer

Linux Kernel TCP/IP Stack — Socket Layer

kernel笔记:TCP参数

Overriding the default Linux kernel 20-second TCP socket connect timeout

Socket 缓冲