一尘不染

通过域套接字传输的单个数据包的大小的实际限制是什么?

linux

让我们假设有一个为典型的服务器-客户端程序创建的Unix域套接字。客户端通过套接字发送10GB的缓冲区,同时服务器将其占用。

OS(Linux / BSD)是将10GB缓冲区分成许多数据包并发送/使用它们,还是一次发送?

如果无法一次性发送10GB的域套接字缓冲区,那么单个数据包的实际大小限制是多少?

限制条件:

  • 该程序将在Linux 2.6.32+和FreeBSD 9+上运行
  • 要发送的缓冲区的大小最大为3个字节,最大为10GB。

阅读 451

收藏
2020-06-07

共1个答案

一尘不染

有许多因素将决定可以在Unix套接字上发送的数据包的最大大小:

  1. wmem_max套接字发送缓冲区的最大尺寸的内核设置,其确定发送的最大大小缓冲器可以使用被设置setsockopt (SO_SNDBUF)。可以读取当前设置/proc/sys/net/core/wmem_max,也可以使用进行设置sysctl net.core.wmem_max=VALUE(添加设置/etc/sysctl.conf以使更改在重新引导后保持不变)。请注意,此设置适用于所有套接字和套接字协议,而不仅适用于Unix套接字。

  2. 如果将多个数据包发送到Unix套接字(使用SOCK_DATAGRAM),则可以无阻塞发送的最大数据量取决于套接字发送缓冲区的大小(请参见上文) Unix上未读数据包的最大数目套接字(内核参数net.unix.max_dgram_qlen)。

  3. 最后,数据包(SOCK_DATAGRAM)需要连续的内存根据[Linux可以发送的AF_UNIX数据报消息的最大大小是多少?)。内核中有多少连续内存取决于许多因素(例如,系统上的I / O负载等)。

因此,为了最大程度地提高应用程序的性能,您需要大的套接字缓冲区大小(以最小化由于套接字写系统调用而导致的用户/内核空间上下文切换)和大的Unix套接字队列(以尽可能地使生产者和使用者分离)
)。但是,套接字发送缓冲区大小和队列长度的乘积不能太大,以免导致内核用尽连续的内存区域(导致写失败)。

实际数字将取决于您的系统配置和使用情况。您将需要通过测试来确定限制…从wmem_max256Kb和max_dgram_qlen32
开始说,然后继续增加一倍,wmem_max直到您注意到事情开始破裂。您将需要进行调整max_dgram_qlen以在一定程度上平衡生产者和消费者的活动(尽管如果生产者比消费者快得多或慢得多,则队列大小不会有太大影响)。

请注意,您的生产者将必须wmem_max通过调用来专门设置套接字发送缓冲区的大小为字节,setsockopt (SO_SNDBUF)并且必须将数据拆分为wmem_max字节块(而使用者将不得不重新组装它们)。

最佳猜测:实际限制将在wmem_max〜8Mb和unix_dgram_qlen〜32附近。

2020-06-07