Я только что переключился с POSIX на SysV, потому что предел для SysV намного выше (1024 против 10). Но мне все еще нужен более высокий предел. Ограничение следует изменить во время выполнения, поскольку оно зависит от данных, которые выбирает пользователь.
Используя POSIX, можно было увеличить лимит, но нужно было каждый раз запускать код от имени пользователя root, а я этого сделать не могу.
Есть ли способ увеличить лимит в SysV?
Какая реализация System V? Например, в Solaris в /etc
был текстовый файл, который мог настраивать (переопределять) значения для ограничений System V IPC во время загрузки. Но детали зависят от конкретных I/S. Лимиты и механизм их изменения не стандартизированы.
the limit is much higher
Это предел сообщений в очереди? Поэтому вместо этого буферизируйте их в пользовательском пространстве. 1024 vs 10
Откуда эти цифры? Измерение? Исходный код? Документация?
Использование очереди для долговременного хранения кажется «не идеальным». Лучше подойдет другое решение (например, база данных).
@JohnBollinger, в этом суть. Если создано слишком много сообщений, программа сохраняет их в очереди сообщений, чтобы в конечном итоге программа могла прочитать их и сообщить пользователю, что эти запросы не были успешными.
@KamilCuk Предел POSIX взят из документации, для Sys V я думаю, что он зависит от машины/системы, для меня это 1024 согласно моим измерениям. Я не могу буферизовать их, потому что я могу прочитать эти сообщения только непосредственно перед завершением программы. До этого момента очередь сообщений используется другими процессами.
Что ж, @EnricoBersanoBegey, я думаю, вы выбрали не тот инструмент для работы. Очереди сообщений — это механизм межпроцессного взаимодействия, а не механизм хранения данных. Поскольку сообщения состоят из данных, у MQ есть компонент хранения, но они не предназначены и не подходят для описанного вами использования. Емкость очереди позволяет производителям сообщений временно опережать потребителей сообщений, но в целом, за исключением коротких промежутков времени, потребители должны не отставать от производителей.
Для этого есть команда: ipcs
@JohnBollinger Вот как работает программа: разные процессы должны взаимодействовать через очередь сообщений. Обычно каждое сообщение читается немедленно, а mq остается пустым. В других случаях (если пользователь выбирает несбалансированные параметры) создается больше сообщений, чем потребляется, и очередь сообщений быстро заполняется. Эти данные не могут быть потеряны и не могут быть помещены в буфер, поскольку другие процессы соглашаются получить эти данные. Я не пытаюсь использовать очередь сообщений в качестве механизма хранения данных. Эта программа завершается через заданное время (обычно секунды или максимум минуты)
--> И, наконец, неиспользуемые сообщения должны быть буферизованы и отображены пользователю
@EnricoBersanoBegey, если дизайн программы зависит от возможности буферизации произвольного количества сообщений в очереди, то да, она использует очередь в качестве механизма хранения. Если пользователь может выбрать параметры, вызывающие такое поведение, то это является недостатком проекта, и настройка предела очереди не является решением — она только изменяет вероятность сбоя программы. Если такие параметры недействительны, программа должна корректно завершать работу, когда не может поставить сообщение в очередь.
Поскольку SYSV IPC считается устаревшим, жаль разрабатывать совершенно новые приложения с этими старомодными сервисами.
Очереди сообщений POSIX основаны на файловой системе. Обычно он монтируется в /dev/mqueue:
$ ls -la /dev/mqueue
total 0
drwxrwxrwt 2 root root 40 dec. 25 21:02 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
Очередь сообщений создается с помощью mq_open(). Параметр attr предоставляет возможность установить некоторые атрибуты:
struct mq_attr {
long mq_flags; /* Flags (ignored for mq_open()) */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue (ignored for mq_open()) */
};
Согласно документации , файл /proc/sys/fs/mqueue/msg_max определяет максимальное значение максимального количества сообщений в очереди. В Linux 5.4 его значение по умолчанию — DFLT_MSGMAX (10), а его верхний предел — HARD_MSGMAX (65536).
Значения по умолчанию определены в исходном коде Linux (см. /include/linux/ipc_namespace.h):
#define DFLT_QUEUESMAX 256
#define MIN_MSGMAX 1
#define DFLT_MSG 10U
#define DFLT_MSGMAX 10
#define HARD_MSGMAX 65536
#define MIN_MSGSIZEMAX 128
#define DFLT_MSGSIZE 8192U
#define DFLT_MSGSIZEMAX 8192
#define HARD_MSGSIZEMAX (16*1024*1024)
Вот пример программы, которая создает очередь сообщений. Он получает в качестве параметров имя очереди сообщений и максимальное количество сообщений в очереди:
#include <errno.h>
#include <pthread.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
mqd_t mqdes;
struct mq_attr attr;
if (argc != 3) {
fprintf(stderr, "Usage: %s <mq-name> <msg_max>\n", argv[0]);
exit(EXIT_FAILURE);
}
attr.mq_flags = 0;
attr.mq_maxmsg = atoi(argv[2]);
attr.mq_msgsize = 2048;
attr.mq_curmsgs = 0;
mqdes = mq_open(argv[1], O_CREAT | O_RDWR, 0777, &attr);
if (mqdes == (mqd_t) -1) {
perror("mq_open");
return 1;
}
return 0;
}
Во время выполнения мы можем убедиться, что по умолчанию мы не можем превышать 10 сообщений для очереди:
$ gcc mq.c -o mq -lrt
$ ./mq
Usage: ./mq <mq-name> <msg_max>
$ ./mq /q0 5
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 60 dec. 25 21:09 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
$ ./mq /q1 9
$ ./mq /q2 10
$ ./mq /q3 11
mq_open: Invalid argument
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 100 dec. 25 21:10 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q1
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q2
Давайте изменим максимальное значение с 10 на 256 для msg_max:
$ cat /proc/sys/fs/mqueue/msg_max
10
$ sudo sh -c "echo 256 > /proc/sys/fs/mqueue/msg_max"
$ cat /proc/sys/fs/mqueue/msg_max
256
Теперь можно создавать очереди сообщений до 256 сообщений:
$ ./mq /q3 11
$ ./mq /q4 256
$ ./mq /q5 257
mq_open: Invalid argument
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 140 dec. 25 21:16 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q1
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q2
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:15 q3
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:16 q4
Но, как вы говорите, для увеличения максимального значения требуются права суперпользователя. Можно было бы создать «помощник setuid», который увеличивает значение потолка. Например, следующая программа задает значение потолка, переданное в качестве параметра:
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
int rc;
int msg_max;
if (argc != 2) {
fprintf(stderr, "Usage: %s <msg_max>\n", argv[0]);
return 1;
}
fd = open("/proc/sys/fs/mqueue/msg_max", O_RDWR);
if (fd < 0) {
perror("open()");
return 1;
}
rc = write(fd, argv[1], strlen(argv[1]));
if (rc != strlen(argv[1])) {
if (rc >= 0) {
errno = EIO;
}
perror("write()");
return 1;
}
close(fd);
return 0;
}
Мы можем собрать его, изменить его владельца/группу на root и добавить бит setuid:
$ gcc mq_helper.c -o mq_helper
$ sudo chown root mq_helper
$ sudo chgrp root mq_helper
$ sudo chmod 4555 mq_helper
$ ls -l mq_helper
-r-sr-xr-x 1 root root 17016 dec. 25 21:45 mq_helper
Затем можно запустить эту программу из учетной записи пользователя без прав суперпользователя, чтобы изменить максимальное значение msg_max:
$ cat /proc/sys/fs/mqueue/msg_max
256
$ ./mq_helper 98
$ cat /proc/sys/fs/mqueue/msg_max
98
Большое спасибо, это очень помогло. К сожалению, я не могу использовать "setuid helper"... он продолжает говорить open(): Permission denied
, хотя я установил все разрешения
Вы установили бит setuid (4555) или, может быть, вы находитесь в контейнере без права записи в файловую систему /proc/sys?
Я установил бит setuid, и никаких ошибок не вышло. ls -l mq_helper
вывод: -r-xr-xr-x 1 root root 16976 Dec 25 15:26 mq_helper
Но у вас нет бита setuid: «s» не отображается на вашем дисплее.
Верно. По какой-то причине у меня возникли проблемы с установкой этого бита, я также пытался запустить sudo chmod u+s mq_helper
. Я постараюсь понять, как это исправить. Большое спасибо
Зачем вам такая длинная очередь сообщений? Я вижу, что 10 - это немного мало, но если 1024 недостаточно, то есть ли какой-либо предел, который действительно подходит? Если вы накапливаете такое количество сообщений одновременно, это звучит так, как будто потребители сообщений не поспевают за производителями сообщений, и более длинная очередь не исправит это.