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

19 unix sockets linux posix ipc

我们假设为典型的服务器 - 客户端程序创建了一个Unix域套接字.客户端在套接字上发送10GB缓冲区,同时由服务器使用.

操作系统(Linux/BSD)将10GB缓冲区分成多个数据包并发送/使用它们,还是一次性发送?

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

约束:

  • 该程序将在Linux 2.6.32+和FreeBSD 9+上运行
  • 要发送的缓冲区大小从3字节到最大10GB不等.

ise*_*dev 29

有许多因素可以决定可以在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上未读数据包的最大数量socket(内核参数net.unix.max_dgram_qlen).

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

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

实际数字取决于您的系统配置和使用情况.您将需要通过测试确定限制...开始说明wmem_max在256Kb和max_dgram_qlen32并且保持加倍,wmem_max直到您发现事情开始破坏.您需要进行调整max_dgram_qlen以在一定程度上平衡生产者和消费者的活动(尽管如果生产者比消费者更快或更慢,则队列大小不会产生太大影响).

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

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