众所周知,getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &opt_val, &opt_len);
返回之前在 setsockopt()中分配的 tcp 缓冲区大小的两倍
.
(如 man 7 tcp
中所写:
请注意,TCP 实际上分配了请求缓冲区大小的两倍
setsockopt(2) 调用,因此后续的 getsockopt(2) 调用将不会返回与 setsockopt(2) 调用中请求的相同大小的缓冲区。 TCP
将额外空间用于管理目的和内部内核结构,
)
所以如果我执行 setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (int *)&buf_size, sizeof(buf_size))
for buf_size = 256K
, 512K
将在 getsockopt()
中分配和返回。
我想计算tcp 缓冲区
中的当前字节数。为此,我正在计算队列中每个数据包的长度 (sk->sk_write_queue->len
) 而 sk
是 struct sock *sk
.
有时返回的长度大于256K
。 (例如,我得到的 294879
字节比 256K
多 32735
字节)。
为什么会这样?
它是否包含 “用于管理目的和内部内核结构的额外空间”
作为 getsockopt(.., SOL_SOCKET, SO_SNDBUF, ..)
?
谢谢。
最佳答案
由于实际分配了 512K,缓冲 294879 字节并不奇怪。 在 Linux 上,当您设置 SO_SNDBUF 时,内核只会将该数量加倍。
如果您希望套接字缓冲区为 256k,请使用 128k 调用 setsockopt()。
现在,所使用的缓冲区不纯粹是为了你的数据,内核需要的skb和其他数据结构都分配在这些缓冲区中,这就是“管理开销”,这相当于多少开销取决于内核如何切片增加你给它的数据——所以只为你从用户空间发送的数据保留 256k 的缓冲区空间是一个相当困难的任务,即使不是几乎不可能完成的任务。
关于c - tcp 缓冲区中的总数据包长度是否可以超过分配的缓冲区大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19652356/