在linux环境下获取所有与tcp缓冲区相关的配置:
net.ipv4.tcp_mem = 64608 86144 129216
net.ipv4.tcp_wmem = 4096 16384 2756608
net.ipv4.tcp_rmem = 4096 87380 2756608
net.core.wmem_max = 262144
net.core.rmem_max = 1048576
net.core.wmem_default = 262144
net.core.rmem_default = 1048576
net.core开头的配置为网络层通用配置,net.ipv4开头的配置为ipv4使用网络配置。
net.core.wmem_max
网络发送窗口最大上限,单位字节,tcp协议里,使用setsockopt()修改SO_SNDBUF时,最大只能修改为【net.core.wmem_max*2】。
net.core.wmem_default
网络发送窗口默认大小,单位字节,在tcp协议里,实际被net.ipv4.tcp_wmem[1]配置覆盖,感觉没什么用处。
net.core.rmem_max
网络接收窗口最大上限,单位字节,tcp协议里,使用setsockopt()修改SO_RCVBUF时,最大只能修改为【net.core.rmem_max*2】。
net.core.rmem_default
网络接收窗口默认大小,单位字节,在tcp协议里,实际被net.ipv4.tcp_rmem[1]配置覆盖,估计是在其他协议里有使用。
net.ipv4.tcp_rmem
tcp协议定义的每个socket链路接收窗口大小,单位字节,有三个值:min、default、max。
min默认为pagesize(4K字节),每一个socket接收窗口大小下限;
default为每个socket建链后默认接收窗口大小,默认值为16K,所谓的窗口大小只是一个限制数值,实际对应的内存缓冲区由协议栈管理分配;
max为每个socket链路接收窗口大小上限,该值只在没有使用setsockopt()修改SNDBUF时有效,用于tcp协议栈自动调整窗口大小的上限。
net.ipv4.tcp_wmem
tcp协议定义的每个socket链路发送窗口大小,单位字节,有三个值:min、default、max,具体含义与net.ipv4.tcp_rmem类似。
net.ipv4.tcp_mem
tcp协议栈所有链路内存占用的限制,单位pagesize(4K),包括3个配置low, pressure, high,一般情况下这些值是在系统启动时根据系统内存数量计算得到,不需要工修改。整个系统tcp链路的内存消耗对应/proc/net/sockstat的“TCP:mem”值。
low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存;
pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态;
high:允许所有tcp sockets用于排队缓冲数据报的页面量,如果超过这个值,TCP 连接将被拒绝,并置errno为“ENOMEM out of socket memory”。
实时观察系统socket使用情况:
cat /proc/net/sockstat
sockets: used 294
TCP: inuse 38 orphan 0 tw 0 alloc 48 mem 4
UDP: inuse 4 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
sockets: used:已使用的所有协议套接字总量
TCP: inuse:正在使用(正在侦听)的TCP套接字数量,其值不大于netstat –lnt | grep ^tcp | wc –l
TCP: orphan:不属于任何进程孤儿TCP连接数(无用、待销毁的TCP socket数)
TCP: tw:等待关闭的TCP连接数,其值等于TIME_WAIT状态链路数
TCP:alloc(allocated):已分配(已建立、已申请到sk_buff)的TCP套接字数量。其值等于netstat –ant | grep ^tcp | wc –l
TCP: mem:套接字缓冲区使用量(单位页大小),对应系统所有tcp链路的内存开销。
UDP: inuse:正在使用的UDP套接字数量
RAW:单纯IP层socket
FRAG:使用的IP段数量
setsockopt()源码:
case SO_SNDBUF:
if (val > sysctl_wmem_max)
val = sysctl_wmem_max; //限制输入val值最大为wmem_max
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;//加锁,限制发送窗口自动调整
if ((val * 2) < SOCK_MIN_SNDBUF)
sk->sk_sndbuf = SOCK_MIN_SNDBUF; //发送窗口最小为2K
else
sk->sk_sndbuf = val * 2; // 实际发送窗口为设置值的2倍
sk->sk_write_space(sk); // 修改发送窗口后,触发发送操作
break;
setsockopt()修改发送窗口、接收窗口都有这些特征:
最大值受限net.core.rmem_max、net.core.wmem_max;
修改后,窗口不能由协议栈自动调整了,默认窗口大小可以在一定范围内变化的;
如果修改正确,实际修改值为传入参数值的2倍。