21

次のような呼び出しによって作成された AF_UNIX ソケットのペアで、奇妙なことがいくつか見られます。

 socketpair(AF_UNIX, SOCK_STREAM, 0, sfd); 

sfd は、ファイル記述子の int[2] 配列です。

まず、デフォルトのバッファー サイズは、/proc/sys/net (128K に設定されている wmem_default など) からのものではなく、正確に 122K (124928 バイト) のようです。この奇妙なバッファサイズの原因を知っている人はいますか?

2 つ目は、ソケット (8 バイト) を介して小さなメッセージを書き込む場合です。書き込みブロックの前に 423 個しか書き込むことができません。これは 8*423 = 3384 バイトで、これも奇妙なサイズです。メッセージは、それぞれ 295 + 少しのバイトを占有しているかのように動作しています。このオーバーヘッドの原因は何ですか?

RHEL6 (2.6.32、64 ビット) で実行

オーバーヘッド コストを比較するために、さまざまなサイズのデータ​​を試すプログラムを作成しました。

#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);
    }
}

これにより、次のことが得られます。

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

パイプを使用する場合と比較して、間違いなく多くのオーバーヘッドがあります。

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
4

2 に答える 2

7

socket(7) の man ページを見てください。次のセクションがあります。

SO_SNDBUF 最大ソケット送信バッファをバイト単位で設定または取得します。setsockopt(2) を使用して設定すると、カーネルはこの値を 2 倍にし (ブックキーピング オーバーヘッドのためのスペースを確保するため)、この 2 倍の値が getsockopt(2) によって返されます。デフォルト値は /proc/sys/net/core/wmem_default ファイルによって設定され、最大許容値は /proc/sys/net/core/wmem_max ファイルによって設定されます。このオプションの最小 (2 倍) 値は 2048 です。

したがって、オーバーヘッドは単にカーネルの簿記情報を保持することであると思われます。

于 2012-06-07T23:25:50.540 に答える
0

net.unix.max_dgram_qlensysctlの値を確認しましたか?

カーネルは、飛行中の AF_UNIX データグラムの最大数に制限を課します。私のシステムでは、制限は実際には非常に低く、わずか 10 です。

于 2012-06-06T16:03:25.200 に答える