【问题标题】:Does Linux raw socket buffer size have upper limit of 256 K?Linux 原始套接字缓冲区大小是否有 256 K 的上限?
【发布时间】:2015-08-31 03:30:27
【问题描述】:

我在 Centos 中使用以下代码将原始套接字缓冲区大小更改为 400 KB,但是当我将缓冲区大小设置为 256 KB 时,我得到了相同的结果。哪里不对了?或者这是套接字层的限制?内核版本为 2.6.34。谢谢!

int       rawsock;
socklen_t socklen;
int       optval;
int       bufsize = 400 * 1024;

rawsock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (rawsock < 0) {
    my_log(LOG_ERR, "error creating raw socket");
    return rawsock;
}

optval = 0;
socklen = 4;
err = getsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &optval, &socklen);
bail_error(err);
my_log("socket RX original buffer size = %d", optval);

optval = 0;
socklen = 4;
err = getsockopt(rawsock, SOL_SOCKET, SO_SNDBUF, &optval, &socklen);
bail_error(err);
my_log("socket TX original buffer size = %d", optval);

err = setsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
bail_error(err);

err = setsockopt(rawsock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
bail_error(err);

optval = 0;
socklen = 4;
err = getsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &optval, &socklen);
bail_error(err);
my_log("socket RX new buffer size = %d", optval);

optval = 0;
socklen = 4;
err = getsockopt(rawsock, SOL_SOCKET, SO_SNDBUF, &optval, &socklen);
bail_error(err);
my_log("socket TX new buffer size = %d", optval);

运行后,结果为:

socket RX original buffer size = 110592
socket TX original buffer size = 110592
socket RX new buffer size = 524288
socket TX new buffer size = 524288

【问题讨论】:

    标签: c sockets buffer embedded-linux setsockopt


    【解决方案1】:

    您刚刚达到了系统当前的 sysctl 限制 net.core.wmem_maxnet.core.rmem_max

    如果进程具有超级用户权限,它可以使用SO_SNDBUFFORCESO_RCVBUFFORCE ioctl 来覆盖限制。如果您的服务确实需要更大的缓冲区有一个真正的原因——也就是说,除了糟糕的开发或设计选择之外的任何其他原因——那么我推荐这种方式。通常没有这样的原因,在这种情况下,我建议您改为修复应用程序/服务代码。

    您可以在系统范围内修改限制,但它们会影响所有进程。通常默认值可以正常工作,但在某些特殊情况下(可能是具有非常宽但长延迟网络连接的嵌入式服务器?)您可能希望修改它们。

    要临时执行此操作(直到下次启动),请以 root 身份运行 sysctl -w net.core.wmem_max=bytessysctl -w net.core.rmem_max=bytes(其中 bytes 是十进制数的新限制,以字节为单位)。

    要使更改永久生效,请添加

    net.core.rmem_max=bytes
    net.core.wmem_max=bytes
    

    到您的/etc/sysctl.conf 文件,或/etc/sysctl.d/ 目录中的新文件(如果您的 Linux 发行版提供)。后者是更好的方法,因为它不会停止对默认配置文件的更新。

    如果您想深入研究这些和其他套接字 ioctl,可以查看内核 net/core/sock.c 文件,以及其中的 sock_setsockopt() 函数。

    【讨论】:

      【解决方案2】:

      根据documentation

      SO_RCVBUF:最大允许值由/proc/sys/net/core/rmem_max文件设置

      SO_SNDBUF :最大允许值由/proc/sys/net/core/wmem_max 文件设置。

      因此限制可能取决于您的系统是如何配置的。

      【讨论】:

        【解决方案3】:

        有趣的旁注。我编写了一个 AF_ALG 程序,该程序接受一个输入文件(将随机选择),对其进行加密、解密,然后将解密后的明文与原始输入进行比较(使用 cbc(aes))。 “测试”程序似乎在 212992 字节处挂起。用 ctrl-z 中断程序,然后进入后台,他们报告读取了 212992 字节(我知道测试数据是错误的,在本例中是 /bin/zip,215792 字节)。

        检查 net.core.[rmem_max, wmem_max, rmem_default, wmem_default],它们是 212992。更新到 2M,之前失败的测试开始工作。因此,这些限制似乎也会影响 AF_ALG 程序(我正在尝试公开一个加密加速器并使用 AF_ALG 使其承受来自用户空间的一些压力)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-17
          相关资源
          最近更新 更多