简体   繁体   English

AF_UNIX套接字开销?

[英]AF_UNIX socket overhead?

I'm seeing a couple strange things with a pair of AF_UNIX sockets created by a call such as: 我看到一些奇怪的东西,一对AF_UNIX套接字由一个调用创建,如:

 socketpair(AF_UNIX, SOCK_STREAM, 0, sfd); 

Where sfd is an int[2] array for the file descriptors. 其中sfd是文件描述符的int [2]数组。

First, the default buffer size seems to be exactly 122K (124928 bytes), rather than anything from /proc/sys/net (such as wmem_default which is set to 128K). 首先,默认缓冲区大小似乎正好是122K(124928字节),而不是/ proc / sys / net中的任何内容(例如设置为128K的wmem_default)。 Does anyone know the cause of this strange buffer size? 有谁知道这个奇怪的缓冲区大小的原因?

Second, when writing small messages through the socket (8 bytes). 第二,通过套接字写入小消息时(8字节)。 I can only write 423 of them before the write blocks, which is only 8*423 = 3384 bytes, another odd size. 我只能在写块之前写入423个,这只是8 * 423 = 3384个字节,另一个是奇数。 The messages are acting as though they're taking up 295 + a little bytes each. 这些消息就好像它们每个占用了295 +一个小字节。 What's the source of this overhead? 这个开销的来源是什么?

Running on RHEL6 (2.6.32, 64-bit) 在RHEL6上运行(2.6.32,64位)

I wrote a program to try different sizes of data to compare overhead costs: 我写了一个程序来尝试不同大小的数据来比较开销成本:

#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define DATA_SIZE 4

void run(size_t size) {
    int sfd[2];
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) == -1) {
        perror("error");
    }


    int sndbuf, sbsize = sizeof(sndbuf);
    getsockopt(sfd[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, (socklen_t*)&sbsize);

    printf("Data Size: %zd\n", size);
    char buff[size];   
    size_t wrote=0;
    for (size_t ii=0; ii < 32768; ii++) {
        if ((send(sfd[0], buff, size, MSG_DONTWAIT) == -1) && (errno == EAGAIN)) {
            wrote = ii;
            break;
        }
    }

    printf("Wrote:     %zd\n", wrote);

    if (wrote != 0) { 
        int bpm = sndbuf/wrote;
        int oh  = bpm - size;

        printf("Bytes/msg: %i\n",  bpm);
        printf("Overhead:  %i\n",  oh);
        printf("\n");
    }

    close(sfd[0]); close(sfd[1]);
}

int main() {
    int sfd[2];
    socketpair(AF_UNIX, SOCK_STREAM, 0, sfd);

    int sndbuf, sbsize = sizeof(sndbuf);
    getsockopt(sfd[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, (socklen_t*)&sbsize);

    printf("Buffer Size: %i\n\n", sndbuf);
    close(sfd[0]); close(sfd[1]);

    for (size_t ii=4; ii <= 4096; ii *= 2) {
        run(ii);
    }
}

Which gives: 这使:

Buffer Size: 124928

Data Size: 4
Wrote:     423
Bytes/msg: 295
Overhead:  291

Data Size: 8
Wrote:     423
Bytes/msg: 295
Overhead:  287

Data Size: 16
Wrote:     423
Bytes/msg: 295
Overhead:  279

Data Size: 32
Wrote:     423
Bytes/msg: 295
Overhead:  263

Data Size: 64
Wrote:     423
Bytes/msg: 295
Overhead:  231

Data Size: 128
Wrote:     348
Bytes/msg: 358
Overhead:  230

Data Size: 256
Wrote:     256
Bytes/msg: 488
Overhead:  232

Data Size: 512
Wrote:     168
Bytes/msg: 743
Overhead:  231

Data Size: 1024
Wrote:     100
Bytes/msg: 1249
Overhead:  225

Data Size: 2048
Wrote:     55
Bytes/msg: 2271
Overhead:  223

Data Size: 4096
Wrote:     29
Bytes/msg: 4307
Overhead:  211

Versus using a pipe there's definitely a lot of overhead: 与使用管道相比,肯定有很多开销:

Data Size: 4
Wrote:     16384
Bytes/msg: 4
Overhead:  0

Data Size: 8
Wrote:     8192
Bytes/msg: 8
Overhead:  0

Data Size: 16
Wrote:     4096
Bytes/msg: 16
Overhead:  0

Data Size: 32
Wrote:     2048
Bytes/msg: 32
Overhead:  0

Data Size: 64
Wrote:     1024
Bytes/msg: 64
Overhead:  0

Data Size: 128
Wrote:     512
Bytes/msg: 128
Overhead:  0

Data Size: 256
Wrote:     256
Bytes/msg: 256
Overhead:  0

Data Size: 512
Wrote:     128
Bytes/msg: 512
Overhead:  0

Data Size: 1024
Wrote:     64
Bytes/msg: 1024
Overhead:  0

Data Size: 2048
Wrote:     32
Bytes/msg: 2048
Overhead:  0

Data Size: 4096
Wrote:     16
Bytes/msg: 4096
Overhead:  0

Take a look at the socket(7) man page. 看一下socket(7)手册页。 There is a section that reads: 有一节内容如下:

SO_SNDBUF Sets or gets the maximum socket send buffer in bytes. SO_SNDBUF以字节为单位设置或获取最大套接字发送缓冲区。 The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). 当使用setsockopt(2)设置时,内核将此值加倍(以便为簿记开销留出空间),并且getsockopt(2)返回此doubled值。 The default value is set by the /proc/sys/net/core/wmem_default file and the maximum allowed value is set by the /proc/sys/net/core/wmem_max file. 默认值由/ proc / sys / net / core / wmem_default文件设置,最大允许值由/ proc / sys / net / core / wmem_max文件设置。 The minimum (doubled) value for this option is 2048. 此选项的最小(加倍)值为2048。

So it appears that the overhead is simply to hold bookkeeping information for the Kernel. 所以看起来开销只是为了保存内核的簿记信息。

Have you looked at the value of the net.unix.max_dgram_qlen sysctl? 你看过net.unix.max_dgram_qlen sysctl的值了吗?

The kernel imposes a limit on the maximum number of in-flight AF_UNIX datagrams. 内核对飞行中AF_UNIX数据报的最大数量施加了限制。 On my system the limit is actually very low: only 10. 在我的系统上,限制实际上非常低:只有10。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM