众所周知,getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &opt_val, &opt_len);
返回之前在setsockopt()
中分配的tcp缓冲区大小的两倍。
(正如man 7 tcp
所述:
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,
)
因此,如果我为setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (int *)&buf_size, sizeof(buf_size))
buf_size = 256K
512K
,则会getsockopt()
分配并返回tcp buffer
。
我想计算sk->sk_write_queue->len
中的当前字节数。为此,我计算队列中每个数据包的长度(sk
),struct sock *sk
为256K
。
有时候返回的长度大于294879
。 (例如,我得到的32735
个字节比256K
多"extra space for administrative purposes and internal kernel structures"
个字节。)
为什么会这样?
它是否包含getsockopt(.., SOL_SOCKET, SO_SNDBUF, ..)
作为{{1}}?
感谢。
答案 0 :(得分:3)
由于512K实际上已经分配,缓冲294879字节并不令人惊讶。 在linux上,当您设置SO_SNDBUF时,内核只会将该数量加倍。
如果您希望套接字缓冲区为256k,请使用128k调用setsockopt()。
现在,使用的缓冲区并不纯粹是针对您的数据,内核需要的skb和其他数据结构都是在这些缓冲区中分配的,这就是“管理开销”,这相当于多少开销取决于内核切片的方式你给它的数据 - 所以只为你从用户空间发送的数据保留256k的缓冲空间是一项相当困难的工作,如果不是几乎不可能的话。