内核套接字结构和TCP_DIAG


18

我正在开发一种连接到实时数据服务器(使用TCP)的软件,但有些连接掉线了。我的猜测是客户端无法足够快地读取来自服务器的数据。因此,我想监视我的TCP套接字。为此,我找到了“ ss”工具。

这个工具可以查看每个套接字的状态-这是命令输出的示例行 ss -inm 'src *:50000'

ESTAB      0      0             184.7.60.2:50000       184.92.35.104:1105
  mem:(r0,w0,f0,t0) sack rto:204 rtt:1.875/0.75 ato:40

我的问题是:记忆部分是什么意思?查看该工具的源代码,我发现数据来自内核结构(sock中的sock.h)。更确切地说,它来自以下领域:

r = sk->sk_rmem_alloc
w = sk->sk_wmem_queued;
f = sk->sk_forward_alloc;
t = sk->sk_wmem_alloc;

有人知道他们的意思吗?我的猜测是:

  • rmem_alloc :入站缓冲区的大小
  • wmem_alloc :出站缓冲区的大小
  • sk_forward_alloc :???
  • sk->sk_wmem_queued :???

这是我的缓冲区大小:

net.ipv4.tcp_rmem = 4096        87380   174760
net.ipv4.tcp_wmem = 4096        16384   131072
net.ipv4.tcp_mem = 786432       1048576 1572864
net.core.rmem_default = 110592
net.core.wmem_default = 110592
net.core.rmem_max = 1048576
net.core.wmem_max = 131071

您的缓冲区大小配置是什么?您是否在套接字连接上看到接收缓冲区饱和?您的聚会是否在EWOULDBLOCK上断开连接?
卡森(Karlson)2012年

我认为我的插座尺寸很小,我用它们更新了帖子。对于EWOULDBLOCK,我无法告诉。我的客户端在JAVA中,只是说它已被服务器断开连接。服务器使用C ++,它只是说他在没有任何信息的情况下断开了连接。我没有服务器的源代码,因此无法更改其行为。似乎客户端在过载时断开连接,即使它仅持续几秒钟。
Twister 2012年

服务器上缓冲区大小的配置是否可调整?您可以在客户端上观看缓冲区大小吗?您可以访问客户的来源吗?您是否运行过netstat -apnc以查看缓冲区大小?您是否尝试增加内核中的缓冲区大小以查看会发生什么?
Karlson 2012年

是的,它们已经设置好,并且已经设置为服务器的最大值(我相信它们不能大于net.ipv4.tcp_ *属性,对吗?)对于netstat -apnc,它不会给我缓冲区的大小,那就是为什么我看着ss。对于内核,我不是服务器上的超级用户,这里的IT团队非常固执。在要求他们更改值之前,我需要确定会发生什么。是的,我可以访问客户端源,并且我对客户端的调查确认断开连接来自服务器。
Twister 2012年

netstat -apnc提供了Linux上发送和接收队列的总大小。如果服务器将缓冲区设置为最大可用缓冲区,而您仍在饱和,则可能需要在OS级别上使用更高的缓冲区设置
Karlson 2012年

Answers:


7

sk_forward_alloc 是前向分配的内存,它是套接字配额中当前可用的总内存。

sk_wmem_queued 是在发送队列中排队的套接字发送缓冲区使用的内存量,尚未发送出去或尚未确认。

您可以在TCP / IP体系结构,Linux中的设计和实现的第9章中了解有关TCP内存管理的更多信息。作者:Sameer Seth,M. Ajaykumar Venkatesulu


我不明白的定义与sk_wmem_queued有何不同sk_wmem_alloc,您能对此做些扩展吗?(如果您知道答案,请随时添加以下问题的答案:unix.stackexchange.com/questions/551444/…
little-dude

1

请参见ss的手册页。

<fwd_alloc>
   The  memory allocated by the socket as cache, but not used for receiving/sending packet yet. If need memory to send/receive packet, the memory in this cache will be used before allocate additional memory.

<wmem_queued>
   The memory allocated for sending packet (which has not been sent to layer 3)

0

关于sk_wmem_queuedsk_wmem_alloc,我问了同样的问题,因此我将答案复制到这里:

我发了电子邮件给Eric Dumazet,他为Linux网络堆栈做出了贡献,这是答案:

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

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

这篇很好(很长)的文章是一个很好的文档,可以理解这三种队列(套接字缓冲区,qdisc队列和设备队列)的含义。简而言之,套接字首先将数据包直接推入qdisc队列,然后将其转发到设备队列。当qdisc队列已满时,套接字开始在其自己的写队列中缓冲数据。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.