【Linux】tcp緩沖區大小的默認值、最大值


Author:阿冬哥

Created:2013-4-17 

Blog:http://blog.csdn.net/c359719435/

Copyright 2013 阿冬哥 http://blog.csdn.net/c359719435/

使用以及轉載請注明出處

 
1 設置socket tcp緩沖區大小的疑惑
       疑惑1:通過setsockopt設置SO_SNDBUF、SO_RCVBUF這連個默認緩沖區的值,再用getsockopt獲取設置的值,發現返回值是設置值的兩倍。為什么?
        通過網上查找,看到linux的內核代碼/usr/src/linux-2.6.13.2/net/core/sock.c,找到sock_setsockopt這個函數的這段代碼:
 
 1       case SO_SNDBUF:
 2                         /* Don't error on this BSD doesn't and if you think
 3                            about it this is right. Otherwise apps have to
 4                            play 'guess the biggest size' games. RCVBUF/SNDBUF
 5                            are treated in BSD as hints */
 6  
 7                         if (val > sysctl_wmem_max)//val是我們想設置的緩沖區大小的值
 8                                 val = sysctl_wmem_max;//大於最大值,則val值設置成最大值
 9  
10                         sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
11                         if ((val * 2) < SOCK_MIN_SNDBUF)//val的兩倍小於最小值,則設置成最小值
12                                 sk->sk_sndbuf = SOCK_MIN_SNDBUF;
13                         else
14                                 sk->sk_sndbuf = val * 2;//val的兩倍大於最小值,則設置成val值的兩倍
15  
16                         /*
17                          *      Wake up sending tasks if we
18                          *      upped the value.
19                          */
20                         sk->sk_write_space(sk);
21                         break;
22  
23                 case SO_RCVBUF:
24                         /* Don't error on this BSD doesn't and if you think
25                            about it this is right. Otherwise apps have to
26                            play 'guess the biggest size' games. RCVBUF/SNDBUF
27                            are treated in BSD as hints */
28  
29                         if (val > sysctl_rmem_max)
30                                 val = sysctl_rmem_max;
31  
32                         sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
33                         /* FIXME: is this lower bound the right one? */
34                         if ((val * 2) < SOCK_MIN_RCVBUF)
35                                 sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
36                         else
37                                 sk->sk_rcvbuf = val * 2;
38                         break;

 

        從上述代碼可以看出:(1)當設置的值val > 最大值sysctl_wmem_max,則設置為最大值的2倍:2*sysctl_wmem_max;
                                    (2)當設置的值的兩倍val*2 > 最小值,則設置成最小值:SOCK_MIN_SNDBUF;
                                    (3)當設置的值val < 最大值sysctl_wmem_max,且 val*2 > SOCK_MIN_SNDBUF, 則設置成2*val。
 
        查看linux 手冊:
1             SO_RCVBUF:              
2                     Sets or gets the maximum socket receive buffer in bytes.  
3                     The kernel doubles this value (to allow space for bookkeeping overhead) when it                     is set using setsockopt(2), 
4                     and this doubled value is returned by getsockopt(2).
5                     The default value is set by the /proc/sys/net/core/rmem_default file, 
6                     and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file.  
7                     The minimum (doubled) value for this option is 256.

 

      查看我的主機Linux 2.6.6 :/proc/sys/net/core/rmem_max:
           4194304 //4M
      查看/proc/sys/net/core/wmem_max:
           8388608   //8M
     所以,能設置的接收緩沖區的最大值是8M,發送緩沖區的最大值是16M。
 
        疑惑2:為什么要有2倍這樣的一個內核設置呢?我的理解是,用戶在設置這個值的時候,可能只考慮到數據的大小,沒有考慮數據封包的字節開銷。所以將這個值設置成兩倍。
 
注:overhead,在計算機網絡的幀結構中,除了有用數據以外,還有很多控制信息,這些控制信息用來保證通信的完成。這些控制信息被稱作系統開銷。
        
2 tcp緩沖區大小的默認值
       建立一個socket,通過getsockopt獲取緩沖區的值如下:
              發送緩沖區大小:SNDBufSize = 16384
              接收緩沖區大小:RCVBufSize = 87380 
 
        疑惑3:linux手冊中,接收緩沖區的默認值保存在/proc/sys/net/core/rmem_default,發送緩沖區保存在/proc/sys/net/core/wmem_default。
[root@cfs_netstorage core]# cat /proc/sys/net/core/rmem_default
1048576
[root@cfs_netstorage core]# cat /proc/sys/net/core/wmem_default
512488
 
        可知,接收緩沖區的默認值是:1048576,1M。發送緩沖區的默認值是:512488,512K。為什么建立一個socket時得到的默認值是87380、16384???
 
        進一步查閱資料發現, linux下socket緩沖區大小的默認值在/proc虛擬文件系統中有配置。分別在一下兩個文件中:
/proc/sys/net/ipv4/tcp_wmem
[root@cfs_netstorage core]# cat /proc/sys/net/ipv4/tcp_wmem
4096    16384   131072  //第一個表示最小值,第二個表示默認值,第三個表示最大值。
/proc/sys/net/ipv4/tcp_rmem
[root@cfs_netstorage core]# cat /proc/sys/net/ipv4/tcp_rmem
4096    87380   174760
 
 
       由此可見,新建socket,選取的默認值都是從這兩個文件中讀取的。可以通過更改這兩個文件中的值進行調優,但是最可靠的方法還是在程序中調用setsockopt進行設置。通過setsockopt的設置,能設置的接收緩沖區的最大值是8M,發送緩沖區的最大值是16M(Linux 2.6.6中)。
 
另一文章中簡單介紹:http://www.linuxidc.com/Linux/2012-08/68874.htm
1. tcp 收發緩沖區默認值
[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_rmem  
4096    87380   4161536
87380  :tcp接收緩沖區的默認值
[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_wmem 
4096    16384   4161536
16384  : tcp 發送緩沖區的默認值

2. tcp 或udp收發緩沖區最大值
[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_max 
131071
131071:tcp 或 udp 接收緩沖區最大可設置值的一半。
也就是說調用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen);  時rcv_size 如果超過 131071,那么
getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等於 131071 * 2 = 262142
[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_max  
131071
131071:tcp 或 udp 發送緩沖區最大可設置值得一半。
跟上面同一個道理

3. udp收發緩沖區默認值
[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_default   
111616:udp接收緩沖區的默認值

[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_default 
111616
111616:udp發送緩沖區的默認值

4. tcp 或udp收發緩沖區最小值
tcp 或udp接收緩沖區的最小值為 256 bytes,由內核的宏決定;
tcp 或udp發送緩沖區的最小值為 2048 bytes,由內核的宏決定


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM