【问题标题】:What is the max size of AF_UNIX datagram message in Linux?Linux 中 AF_UNIX 数据报消息的最大大小是多少?
【发布时间】:2011-06-11 09:18:34
【问题描述】:

目前我达到了 130688 字节的硬限制。如果我尝试在一条消息中发送更大的内容,我会收到 ENOBUFS 错误。

我已经检查了net.core.rmem_defaultnet.core.wmem_defaultnet.core.rmem_maxnet.core.wmem_maxnet.unix.max_dgram_qlen sysctl 选项并增加了它们,但它们没有效果,因为这些处理的是总缓冲区大小而不是消息大小.

我还设置了SO_SNDBUFSO_RCVBUF 套接字选项,但这与上面的问题相同。无论如何,默认套接字缓冲区大小都是基于默认套接字选项设置的。

我查看了在套接字堆栈中返回ENOBUFS 的内核源代码,但我不清楚它来自哪里。似乎返回此错误的唯一地方与无法分配内存有关。

最大尺寸实际上是 130688 吗?如果不可以不重新编译内核就可以改变吗?

【问题讨论】:

  • 那是一个巨大的数据报。在我看来,当你有这么大的数据报时,你可能已经使用了 TCP。
  • 是的,这没有帮助。正如我在帖子中所说,无论您的 wmem 设置如何,它都不会让您通过 130688 发送消息。我有它们超过 32MB,并尝试了许多低于此的组合。
  • 只是补充一点。将发送缓冲区和接收缓冲区用于单个消息是一种误解。缓冲区是所有消息的总内核缓冲区。 wmem 和 qlen sysctl 选项实际上会影响发送块的方式和时间。随着发送缓冲区填满(假设没有人接收),当缓冲区中的总字节数超过缓冲区大小或总计数超过 qlen 时,发送将阻塞。
  • 我明白你的观点(和问题)更好。编辑了令人困惑的评论并进行了投票;将在时间允许的情况下四处探索,因为我也对答案感兴趣。
  • 我同意这可能是硬限制。只是想找到一些证据,也许还有一些背后的原因。

标签: sockets unix dns datagram


【解决方案1】:

AF_UNIX SOCK_DATAGRAM/SOCK_SEQPACKET 数据报需要连续内存。连续的物理内存很难找到,分配失败,在内核日志上记录类似这样的内容:

udgc: page allocation failure. order:7, mode:0x44d0
[...snip...]
DMA: 185*4kB 69*8kB 34*16kB 27*32kB 11*64kB 1*128kB 1*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3788kB
Normal: 13*4kB 6*8kB 100*16kB 62*32kB 24*64kB 10*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 7012kB
[...snip...]

unix_dgram_sendmsg() 调用sock_alloc_send_skb() lxr1,它调用sock_alloc_send_pskb()data_len = 0 和header_len = 数据报大小lxr2sock_alloc_send_pskb() 从“正常”skbuff 缓冲区空间分配header_len,从分散/收集页面lxr3 分配data_len。因此,在当前的 Linux 上,AF_UNIX 套接字似乎不支持分散/聚集。

【讨论】:

  • 出色的工作。这基本上是我在痕迹中发现的,但您提供了实际原因。我想知道为什么数据报会有这个限制而不是流?
  • SOCK_STREAM 套接字不保留消息边界。
  • 另请参阅stackoverflow.com/questions/21856517/…的扩展答案
  • SOCK_STREAM 套接字肯定会保留消息边界。只需将每条消息放入一个单独的流中:创建一个新套接字,连接它,写入消息,在发送方向关闭它,接收回复,然后断开连接。然后重复下一条消息。也就是说,连接支持成帧,因为它们明确定义了“流开始”和“流结束”信令;他们只是不支持在流中取景。就像 SOCK_DGRAM 套接字不支持在数据报中分帧一样。
  • @Kaz,所以,他们没有,你必须伪造它。
猜你喜欢
  • 2011-12-07
  • 2016-01-23
  • 2013-03-04
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
相关资源
最近更新 更多