Linux UDP接收缓冲区的最大大小

13

Linux UDP接收缓冲区的最大大小是多少?我原以为它仅受可用RAM的限制,但当我设置rmem_max为5GB时:

echo 5000000000 > /proc/sys/net/core/rmem_max

而在 Erlang 中,实际套接字缓冲区为 4GB:

gen_udp:listen(Port, [{recbuf, 4000000000}])

当我测量缓冲区利用率时,显示:

# netstat -u6anp | grep 5050
udp6  1409995136      0 :::5050  :::*       13483/beam.smp

我不能超过这个1.4GB。对于较小的缓冲区大小,例如500MB,实际缓冲区大小与配置值匹配。我的系统是Debian 6.0,该机器有50GB可用RAM。


1
它在哪里说仅受可用RAM的限制?你为什么认为你需要一个4GB缓冲区? - user207421
它没有限制。它也没有以任何其他方式受到限制。我需要这样的缓冲区来避免在较长的网络流量峰值期间发生数据丢失。 - Wacław Borowiec
1
相反,它说内核可能会调整您提供的值,并建议您调用 getsockopt() 查看实际分配的值。我觉得很难相信您需要4GB来处理流量峰值。也许你只需要更快地读取。 - user207421
“它说内核可能会调整您提供的值的大小”,你在哪里找到这个信息?如何在一个线程中比“while(true){recv(Socket)}”更快地读取?为了测试,我在接收后丢弃数据包。我能够每秒读取60000个大小为600B的数据包,而生成200000/s的流量也不是问题。在这些条件下,缓冲区在16秒后就会填满。你不能客观地说10秒是峰值,而20秒不是。我更希望用一台更好的机器来延长峰值的时间。 - Wacław Borowiec
我已经在man页面上读到那个语句超过20年了,这并不是新闻。你怎么知道你正在接收端丢弃数据包? - user207421
2个回答

12

看起来Linux有一个限制。 我已经尝试将rmem_max设置为2 ^ 32-1并成功了。

   root@xxx:/proc/sys/net/core# echo 2147483647 > rmem_max
   root@xxx:/proc/sys/net/core# cat rmem_max
   2147483647

2^32太大了:

   root@xxx:/proc/sys/net/core# echo 2147483648 > rmem_max
   root@xxx:/proc/sys/net/core# cat rmem_max
   -18446744071562067968

将设置为5000000000会产生以下结果:

   root@xxx:/proc/sys/net/core# echo 5000000000 > rmem_max
   root@xxx:/proc/sys/net/core# cat rmem_max
   705032704

我已在Python中进行了测试,使用以下方法来设置和获取套接字接收缓冲区:

   ss.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, bufferSize)
   print ss.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
如果“bufferSize”小于1024^3,则程序会打印出双倍的“bufferSize”,否则回退到256。
705032704×2 = 1410065408,接近于netstat获得的1409995136。

1
实际上,我还没有验证rmem_max中放置的实际值。看起来缓冲区大小被限制为有符号整数,而没有明确的原因。 - Wacław Borowiec
哪个内核版本?32位还是64位? - Massimo
@Massimo这家伙有50吉字节的RAM,我认为可以假定是64位。 - lenny
@lennyy 一个32位操作系统可以通过CPU的物理地址扩展功能寻址高达64GB的RAM。只是单个32位进程最多只能寻址2-4GB。但操作系统本身可以,它可以通过为每个进程的地址空间使用虚拟内存来将该RAM切片分配给多个进程。 - Remy Lebeau
@RemyLebeau 哦,有趣,我不知道那个。虽然很有道理。谢谢分享。 - lenny
@RemyLebeau 我想知道是否有人在使用它。实际上,多年来我接触的所有环境中都只看到64位操作系统。 - Evgeniy Berezovsky

0

2^32-1(2147483647,最大的32位有符号整数)

root@root@localhost:~# sysctl -w net.core.rmem_max=2147483647
net.core.rmem_max = 2147483647

root@localhost:~# sysctl -w net.core.rmem_max=2147483648
sysctl: setting key "net.core.rmem_max": Invalid argument
net.core.rmem_max = 2147483648

回显到 /proc 文件系统时,尝试设置较大值似乎会导致溢出。

哪个内核版本?32位还是64位? - Massimo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接