AF_UNIX套接字的开销? [英] AF_UNIX socket overhead?

查看:193
本文介绍了AF_UNIX套接字的开销?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到一对夫妇奇怪的东西有一对被调用创建AF_UNIX套接字如:

  socketpair(AF_UNIX,SOCK_STREAM,0,SFD);

在哪里SFD是一个i​​nt [2]数组的文件描述符。

首先,默认缓冲区大小似乎正好122K(124928字节),而不是任何东西从/ proc / SYS /网(如被设置为128K wmem_default)。有谁知道这个奇怪的缓冲区大小的原因是什么?

二,通过插座(8字节)编写小消息时。我只能写块,这是只有8 * 423 = 3384字节,另一个奇怪的大小之前写他们的423。这些消息作为虽然他们正在采取的每个295 +一点点字节。这是什么开销的来源?

运行在RHEL6(2.6.32,64位)

我写了一个程序来尝试不同的数据大小,以比较间接成本:

 的#include<&errno.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&stdint.h GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>#定义DATA_SIZE 4无效的run(为size_t大小){
    INT SFD [2];
    如果(socketpair(AF_UNIX,SOCK_STREAM,0,SFD)== -1){
        PERROR(错误);
    }
    INT sndbuf,SBSIZE = sizeof的(sndbuf);
    的getsockopt(SFD [0],SOL_SOCKET,SO_SNDBUF,&放大器; sndbuf,(socklen_t的*)及SBSIZE);    的printf(数据大小:ZD%\\ n,大小);
    字符的buff【规格】;
    为size_t写道= 0;
    为(为size_t二= 0; II蛋白酶32768;ⅱ++){
        如果((发送(SFD [0],浅黄色,大小,MSG_DONTWAIT)== -1)及及(错误号== EAGAIN)){
            写=二;
            打破;
        }
    }    的printf(中写道:ZD%\\ n,写);    如果(写!= 0){
        INT BPM = sndbuf /写;
        诠释哦= BPM - 大小;        的printf(字节/消息:%I \\ N,BPM);
        的printf(开销:%I \\ N,哦);
        的printf(\\ n);
    }    关闭(SFD [0]);关闭(SFD [1]);
}诠释主(){
    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(缓冲大小:%我的\\ n \\ n,sndbuf);
    关闭(SFD [0]);关闭(SFD [1]);    为(为size_t二= 4;ⅱ&下; = 4096;ⅱ* = 2){
        运行(二);
    }
}

这给出了:

 缓冲区大小:124928数据大小:4
写道:423
字节/消息:295
开销:291数据大小:8
写道:423
字节/消息:295
开销:287数据大小:16
写道:423
字节/消息:295
开销:279数据大小:32
写道:423
字节/消息:295
开销:263数据大小:64
写道:423
字节/消息:295
开销:231数据大小:128
写道:348
字节/消息:358
开销:230数据大小:256
写道:256
字节/消息:488
开销:232数据大小:512
写道:168
字节/消息:743
开销:231数据大小:1024
写道:100
字节/消息:1249
开销:225数据大小:2048
写道:55
字节/消息:2271
开销:223数据大小:4096
写道:29
字节/消息:4307
开销:211

与使用管道肯定有很多的开销:

 数据大小:4
写道:16384
字节/消息:4
开销:0数据大小:8
写道:8192
字节/消息:8
开销:0数据大小:16
写道:4096
字节/消息:16
开销:0数据大小:32
写道:2048
字节/消息:32
开销:0数据大小:64
写道:1024
字节/消息:64
开销:0数据大小:128
写道:512
字节/消息:128
开销:0数据大小:256
写道:256
字节/消息:256
开销:0数据大小:512
写道:128
字节/消息:512
开销:0数据大小:1024
写道:64
字节/消息:1024
开销:0数据大小:2048
写道:32
字节/消息:2048
开销:0数据大小:4096
写道:16
字节/消息:4096
开销:0


解决方案

看一看插座(7)手册页。还有,上面写着一个部分:


  

SO_SNDBUF
                设置或获取以字节为单位的最大套接字发送缓冲区。内核双打这个值
                (允许簿记开销空间),当它被使用的setsockopt(2)设置,并且这
                倍值被的getsockopt返回(2)。默认值是由设置
                的/ proc / SYS /网/核心/ wmem_default文件和最大允许值是由设置
                的/ proc / SYS /网/核心/ wmem_max文件。此选项的最小值(加倍)值
                2048


所以看来开销仅仅是持有记账内核信息。

I'm seeing a couple strange things with a pair of AF_UNIX sockets created by a call such as:

 socketpair(AF_UNIX, SOCK_STREAM, 0, sfd); 

Where sfd is an int[2] array for the file descriptors.

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). Does anyone know the cause of this strange buffer size?

Second, when writing small messages through the socket (8 bytes). I can only write 423 of them before the write blocks, which is only 8*423 = 3384 bytes, another odd size. The messages are acting as though they're taking up 295 + a little bytes each. What's the source of this overhead?

Running on RHEL6 (2.6.32, 64-bit)

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. There is a section that reads:

SO_SNDBUF Sets or gets the maximum socket send buffer in bytes. 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). 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. The minimum (doubled) value for this option is 2048.

So it appears that the overhead is simply to hold bookkeeping information for the Kernel.

这篇关于AF_UNIX套接字的开销?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆