Есть ли предел выше max_dgram_qlen и wmem_ {max, default}? - PullRequest
1 голос
/ 04 ноября 2019

Я пытаюсь определить различные пределы сокетов датаграмм unix, поскольку я использую его в качестве IPC для своего проекта. Непонятная вещь, которую я хочу контролировать, это размер внутреннего буфера моего сокета: Я хочу знать, сколько дейтаграмм я могу отправить до того, как мой сокет заблокируется.

Я понял, что 2Разные ограничения влияют на размер буфера сокета:

  1. /proc/sys/net/core/wmem_{max, default} устанавливает максимальный (-default) размер буфера записи сокета
  2. /proc/sys/net/unix/max_dgram_qlen устанавливает максимальное количество дейтаграммбуфер может содержать

Я знаю, что /proc/sys/net/core/rmem_{max, default} устанавливает максимальный (-default) размер буфера чтения сокета, но, поскольку я работаю с локальным сокетом unix, это, похоже, не оказывает влияния.

Я установил wmem_{max, default} на 136314880 (130 МБ) и max_dgram_qlen на 500000. И написал небольшую программу, в которой сокет отправителя отправляет только дейтаграмму фиксированного размера в сокет получателя, пока не будет заблокирован, язатем напечатайте размер и номер дейтаграммы, которую я смог отправить.

Вот код, который я использовал:

#include <err.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>

/* Payload size in bytes. */
#define PAYLOAD_SIZE 100

#define CALL_AND_CHECK(syscall)                 \
    if (syscall < 0) { err(1, NULL); }

int main(void)
{
    int receiver_socket_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
    if (receiver_socket_fd < 0)
        err(1, NULL);

    char* binding_path = "test_socket";
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, binding_path, sizeof(addr.sun_path));

    /* Check if the file exists, if yes delete it ! */
    if (access(binding_path, F_OK) != -1) {
        CALL_AND_CHECK(unlink(binding_path));
    }
    CALL_AND_CHECK(bind(receiver_socket_fd, (struct sockaddr const*) &addr, sizeof(addr)));

    int sender_socket_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
    if (sender_socket_fd < 0)
        err(1, NULL);
    CALL_AND_CHECK(connect(sender_socket_fd, (struct sockaddr const*) &addr, sizeof(addr)));

    struct payload { char data[PAYLOAD_SIZE]; };
    /* Create test payload with null bytes. */
    struct payload test_payload;
    memset(&test_payload.data, 0, PAYLOAD_SIZE);

    ssize_t total_size_written = 0;
    ssize_t size_written = 0;
    do {
        size_written = write(sender_socket_fd, (const void *) &test_payload, PAYLOAD_SIZE);
        if (size_written > 0)
            total_size_written += size_written;
    } while (size_written > 0);

    printf("socket_test: %zu bytes (%ld datagrams) were written before blocking, last error was :\n", total_size_written, total_size_written / PAYLOAD_SIZE);
    perror(NULL);

    CALL_AND_CHECK(unlink(binding_path));
    CALL_AND_CHECK(close(sender_socket_fd));
    CALL_AND_CHECK(close(receiver_socket_fd));


    return 0;
}

Я ожидал достичь максимального размера в байтах сокета(здесь 130MB) или тМаксимальное количество дейтаграмм, которое я установил (500 000).

Но фактический результат заключается в том, что я могу записать только 177494 дейтаграмм до того, как их заблокируют.

Я могуизмените размер моей полезной нагрузки, это всегда тот же самый результат (пока я не достигаю максимального размера в байтах сначала). Поэтому кажется, что я достигаю предела выше max_dgram_qlen и wmem_ {max, default} , который я не могу найти.

Я, конечно, пытался исследовать ulimit или limits.conf безуспешно. ulimit -b даже не работает на моей машине (говорит "опции не найдены" и возвращает). Я работаю над Debian 10 (buster), но запустил мою тестовую программу на разных ОС с тем же результатом: я достиг предела дейтаграммы, о котором я не знаю.

Есть ли у вас какие-либо идеи о том, какиелимит я не видел и достигал? И могу ли я прочитать или изменить этот лимит?

...