http://bbs.chinaunix.net/thread-3777707-1-1.html
Q:通过查看/proc/sys/net/core/rmem_max,在B嵌入式设备上UDP最大缓冲区是32767字节,我想把它调大为65535
请问各位大侠 /proc/sys/net/core/rmem_max Linux默认的UDP缓冲区大小修改之后,除了对内存产生影响外,其它还有什 么影响吗?
A:
rmem_max:控制的是你的socket接受收据的最大值(不限于TCP/UDP协议)。
这个数值的大小取决于你希望你的socket接受的数据的最大值。
比如:
你希望通过socket来recv()数据的时候一次性拿多少。
其实内核在接受数据的时候会buffer接受好的数据,
至于用户也就是你的应用程序希望一次性读多少取决于内核buffer的大小以及已经处理好的数据有多少。
协议栈不会调用setsockopt,而是由创建socket的应用程序调用。rmem_max是个内核调优参数,可以通过/proc/system/net/core/rmem_max进行调整。rmem_max是内核接受数据缓冲的大小,当然不是一次接受的大小,应用程序希望一次接受的大小是在recv()的参数来指定,但指定的这个大小最大是rmem_max,即内核会以rmem_max来缓存数据并在应用调用recv()的时候进行处理(如果recv()指定的大小大于rmem_max则将rmem_max的数据copy给应用;否则按照应用的要求大小进行copy)
/proc/sys/net/core/rmem_max 的含义是指内核最多为一个socket缓存多少数据。
比如你echo "65535" > /proc/sys/net/core/rmem_max
减少A程序read这个socket,B程序从另一台服务器发送数据包,如果A的处理速度非常慢,B的发送速度非常快,当内核socket缓存超过65535字节后,B发送的数据包就会被A的内核丢弃。
1:
Buffer size
The maximum sizes for socket buffers declared via the SO_SNDBUF and SO_RCVBUF
mechanisms are limited
by the values in the /proc/sys/net/core/rmem_max and
/proc/sys/net/core/wmem_max files. Note that
TCP actually allocates twice the
size of the buffer requested in the setsockopt(2) call, and so a succeeding
getsockopt(2) call will not return the same size of buffer as requested in the
setsockopt(2) call. TCP uses the extra space for administrative purposes and
internal kernel structures, and the /proc file values reflect the larger sizes
compared to the actual TCP windows. On individual connections, the socket
buffer size must be set prior to the listen(2) or connect(2) calls in order to
have it take effect. See socket(7) for more information.
由上文可看出,socket缓存大小不仅取决于setsockopt设置的大小,还受限于/proc/sys/net/core/rmem_max and /proc/sys/net/core/wmem_max
我看了协议栈代码,调用setsockopt时设置缓冲区时,是会与/proc/sys/net/core/wmem_max
比较的,这个我已经理解了。
Q:我还碰到一个问题,在Linux上(内核版本2.6.2)与windows XP上做了如下对比:
1):创建一个UDP套接字,发送缓冲区和接收缓冲区都设置为32K
2):Linux发送32K数据(用户数据),windows可以接收到32K,但是windows发32K数据,Linux接收不到,
只有在发小于等于27K,Linux才可以接收到,测试数据如下:
我的疑问时,调用setsockopt设置的接收缓冲区不是用户可用的缓冲区吗?为什么Linux放不下那么大的数据呢?
Linux是不是又做过什么特殊处理?
UDP由于BUFFER
SIZE引起的丢包问题
参见《UNIX® Network Programming Volume 1》 中 8.13 Lack of Flow Control with UDP
注意如下描述:
Why do we set the receive socket buffer size to 220 x 1,024 in Figure 8.22? The maximum size of a socket receive buffer in FreeBSD
5.1 defaults to 262,144 bytes (256 x 1,024), but due to the buffer allocation policy (described in Chapter 2 of TCPv2), the actual limit is 233,016 bytes. Many earlier systems based on 4.3BSD restricted the size of a socket buffer to around 52,000 bytes
所以可以解答Linux 系统是32K 发送数据也是32K,为什么在27K时可以接收成功,看样子是由于BUFFER里面除了数据还包括一些头结构,导致真正可用数据不到32K.
Linux设置的这个缓冲区实际上不是用户可用的缓冲区,
Linux基于sk_buff数据结果进行网络数据收发,每个IP包都会有个sk_buff数据结果而且还包括整个的报文,因此会大大降低实际应用缓冲区,我发现2.6.16内核版本对
/proc/sys/net/core/wmem_max 默认值已经包含了sk_buff的大小,不知我说的对否?