Я пытаюсь определить различные пределы сокетов датаграмм unix, поскольку я использую его в качестве IPC для своего проекта. Непонятная вещь, которую я хочу контролировать, это размер внутреннего буфера моего сокета: Я хочу знать, сколько дейтаграмм я могу отправить до того, как мой сокет заблокируется.
Я понял, что 2Разные ограничения влияют на размер буфера сокета:
/proc/sys/net/core/wmem_{max, default}
устанавливает максимальный (-default) размер буфера записи сокета /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), но запустил мою тестовую программу на разных ОС с тем же результатом: я достиг предела дейтаграммы, о котором я не знаю.
Есть ли у вас какие-либо идеи о том, какиелимит я не видел и достигал? И могу ли я прочитать или изменить этот лимит?