sock->sk_wmem_alloc 和 sock->sk_wmem_queued 有什么区别

lit*_*ude 4 linux networking kernel linux-kernel

sock中定义的结构体有sock.h两个看起来非常相似的属性:

  • sk_wmem_alloc,定义为“已提交的传输队列字节”
  • sk_wmem_queued,定义为“持久队列大小”

对我来说,这sk_wmem_alloc是当前分配给发送队列的内存量。但那么,什么是sk_wmem_queued

参考

  • 根据StackOverflow 的回答

    wmem_queued:在传输队列中排队且尚未发送或尚未确认的套接字发送缓冲区使用的内存量。

  • ss男子还给出了定义,但并没有真正启发我(我不明白IP层与此有什么关系):

    wmem_alloc:用于发送数据包(已发送到第 3 层)的内存 wmem_queued:用于发送数据包(尚未发送到第 3 层)分配的内存

  • 已经有人在 LKML 上问过类似的问题,但没有得到答案
  • 手册sock_diag(7)页也对这些属性有自己的定义:

    SK_MEMINFO_WMEM_ALLOC:发送队列中的数据量。 SK_MEMINFO_WMEM_QUEUED:TCP 排队但尚未发送的数据量。

所有这些定义都是不同的,并且没有一个清楚地解释_alloc_queued变体如何不同。

lit*_*ude 8

我给 Linux 网络堆栈的贡献者 Eric Dumazet 发了一封电子邮件,答案如下:

sk_wmem_alloc跟踪传输堆栈后排队的 skb 字节数:qdisc 层和 NIC TX 环形缓冲区。

如果 TCP 写入队列中有 1 MB 数据尚未发送(cwnd 限制),sk_wmem_queue则约为 1MB,但sk_wmem_alloc约为 0

这篇文章(相当长)是了解这三种类型的队列(套接字缓冲区、qdisc 队列和设备队列)的一个非常好的文档。简而言之,套接字首先将数据包直接推送到 qdisc 队列,然后将它们转发到设备队列。当 qdisc 队列已满时,套接字开始在自己的写入队列中缓冲数据。

网络堆栈将数据包直接放入排队规则中,或者如果队列已满,则将数据包推回到上层(例如套接字缓冲区)

所以基本上:sk_wmem_queues是套接字缓冲区 ( sock.sk_write_queue) 使用的内存,而sk_wmem_alloc是 qdisc 和设备队列中的数据包使用的内存。