在 UDP 套接字上动态更改 SOL_SOCKET、SO_RCVBUF 的可预测行为是什么?
What is the predictable behavior of changing SOL_SOCKET, SO_RCVBUF on the fly on a UDP socket?
如果我们在 Linux 系统上即时调整 UDP 服务器套接字的输入缓冲区大小,应该会发生什么?
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ...)
我对这些问题特别感兴趣:
- 如果我缩小到低于缓冲区中的当前值,这会直接删除 oldest/newest 吗?正确地处理数据报,或者它会刷新那里的所有内容,或者更糟的是它会破坏数据,例如截断数据报吗?
- 缩小缓冲区是否会节省内存或阻止内存被系统重用?
- 行为是可预测的还是有时会随机行为?
首先也是最重要的:术语“缓冲区”可能令人困惑:内核实际上并不将数据包保存在固定大小的缓冲区中,而是保存在称为“积压”的队列中(参见 include/net/sock.h:400
)。通过SO_RCVBUF
和SO_SNDBUF
设置的大小只限制了backlog的最大大小。
If I shrink below what is currently in the buffer, would this simply drop the oldest/newest?
不,已经收到的会保留。没有数据报被丢弃。当您执行 setsockopt(SO_RECVBUF)
时唯一发生的事情是 the value of the sk_rcvbuf
field of the socket is changed。没有执行其他操作。
只有当接收到更多的数据包时才会看到真正的效果:所有后续接收到的数据报将被立即丢弃,并且将继续被丢弃直到队列缩小到设定大小以下(即用户空间接收到足够的数据报)。
Would shrinking the buffer even save memory or something prevents that memory from being reused by the system?
正如我之前所说,由于“缓冲区”并不是真正的缓冲区并且没有固定大小,因此更改 SO_RECVBUF
不会立即更改任何内容。
有两种情况:
- 如果积压大小低于(或等于)指定大小:新的最大大小将受到限制,因此它将节省内存未来 以可能丢失数据包为代价。
- 如果积压大小高于指定大小:当用户空间收到缓冲数据包时,内存最终将被释放,并且不会再次增长超过设定值。这将在将来再次节省内存。
Is the behavior predictable or could it behave randomly at times?
看看内核代码,我会说 100% 可以按照我上面描述的方式进行预测。但是我不完全确定这可能被记录在哪里。如果您将发送和接收“缓冲区”视为队列(它们实际上是),我会说这很直观。
如果我们在 Linux 系统上即时调整 UDP 服务器套接字的输入缓冲区大小,应该会发生什么?
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ...)
我对这些问题特别感兴趣:
- 如果我缩小到低于缓冲区中的当前值,这会直接删除 oldest/newest 吗?正确地处理数据报,或者它会刷新那里的所有内容,或者更糟的是它会破坏数据,例如截断数据报吗?
- 缩小缓冲区是否会节省内存或阻止内存被系统重用?
- 行为是可预测的还是有时会随机行为?
首先也是最重要的:术语“缓冲区”可能令人困惑:内核实际上并不将数据包保存在固定大小的缓冲区中,而是保存在称为“积压”的队列中(参见 include/net/sock.h:400
)。通过SO_RCVBUF
和SO_SNDBUF
设置的大小只限制了backlog的最大大小。
If I shrink below what is currently in the buffer, would this simply drop the oldest/newest?
不,已经收到的会保留。没有数据报被丢弃。当您执行 setsockopt(SO_RECVBUF)
时唯一发生的事情是 the value of the sk_rcvbuf
field of the socket is changed。没有执行其他操作。
只有当接收到更多的数据包时才会看到真正的效果:所有后续接收到的数据报将被立即丢弃,并且将继续被丢弃直到队列缩小到设定大小以下(即用户空间接收到足够的数据报)。
Would shrinking the buffer even save memory or something prevents that memory from being reused by the system?
正如我之前所说,由于“缓冲区”并不是真正的缓冲区并且没有固定大小,因此更改 SO_RECVBUF
不会立即更改任何内容。
有两种情况:
- 如果积压大小低于(或等于)指定大小:新的最大大小将受到限制,因此它将节省内存未来 以可能丢失数据包为代价。
- 如果积压大小高于指定大小:当用户空间收到缓冲数据包时,内存最终将被释放,并且不会再次增长超过设定值。这将在将来再次节省内存。
Is the behavior predictable or could it behave randomly at times?
看看内核代码,我会说 100% 可以按照我上面描述的方式进行预测。但是我不完全确定这可能被记录在哪里。如果您将发送和接收“缓冲区”视为队列(它们实际上是),我会说这很直观。