POSIX queues and msg_max
No.
That limit is a system-wide limit; that's why it's in /proc/sys
. If you want to change it you will have to use the echo
command you have already shown.
Is there a way to increase the maximum amount of messages that can be contained in a SysV message queue?
As SYSV IPC are considered deprecated, it is a pity to design brand new applications with thoses old fashioned services.
POSIX message queues are based on a file system. It is usually mounted on /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 ..
A message queue is created with mq_open(). The attr parameter provides the ability to set some attributes:
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()) */
};
According to the documentation, the /proc/sys/fs/mqueue/msg_max file defines the ceiling value for the maximum number of messages in a queue. In Linux 5.4, its default value is DFLT_MSGMAX (10) and its upper limit is HARD_MSGMAX (65536).
The defaults values are defined in the Linux source code (cf. /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)
Here is an example program which creates a message queue. It receives as parameters the message queue name and the maximum number of messages in the queue:
#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;
}
At execution time we can verify that, by default, we can't go above 10 messages for the queue:
$ 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
Let's change the ceiling value from 10 to 256 for 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
Now it is possible to create message queues with up to 256 messages:
$ ./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
But as you say, increasing the ceiling value requires super user rights. It could be possible to create a "setuid helper" which increases the ceiling value. For example, the following program sets the ceiling value passed as parameter:
#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;
}
We can build it, change its owner/group to root and add the setuid bit:
$ 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
Then, it is possible to run this program from a non super user account to change the ceiling value of msg_max:
$ cat /proc/sys/fs/mqueue/msg_max
256
$ ./mq_helper 98
$ cat /proc/sys/fs/mqueue/msg_max
98
adjust number of messages in posix message queue
In the linux manual page for posix message queue, you can read how to tune the related kernel configuration via the /proc filesystem.
In particular /proc/sys/fs/mqueue/msg_max is what you are looking for:
This file can be used to view and change the ceiling value for the maximum number of messages in a queue. This value acts as a ceiling on the attr->mq_maxmsg argument given to mq_open(3). The default value for msg_max is 10. The minimum value is 1 (10 in kernels before 2.6.28). The upper limit is HARD_MAX: (131072 / sizeof(void *)) (32768 on Linux/86). This limit is ignored for privileged processes (CAP_SYS_RESOURCE), but the HARD_MAX ceiling is nevertheless imposed.
edit
As explained in the mq_open(2), mq_getattr(3) and mq_send(3) manual pages, the mq_maxmsg value sets the maximum number of message that the queue can handle without blocking (or returning EAGAIN in case of non-blocking queues). If you mq_open a queue with mq_maxmsg = 5 and the kernel configuration in /proc is 10 (the default, AFAIK) than the queue will accept 5 message without blocking. If you mq_open a queue with mq_maxmsg = 15 and the kernel configuration in /proc is 10, the queue will accept 10 message. That is: you can create a queue that hold a max number of message that is lower than the maximum number of messages that the kernel accepts, but not greater.
Is it possible to open message queue in linux with huge number of elements?
You have encountered RLIMIT_MSGQUEUE
limit, see mq_overview(7)
:
Resource limit
The
RLIMIT_MSGQUEUE
resource limit, which places a limit on the
amount of space that can be consumed by all of the message queues
belonging to a process's real user ID, is described ingetrlimit(2)
.
Increase it before calling mq_open()
, e.g. like this:
...
#include <sys/resource.h>
int main(int argc, char** argv)
{
struct rlimit rlim;
rlim.rlim_cur = RLIM_INFINITY;
rlim.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_MSGQUEUE, &rlim) == -1) {
perror("setrlimit");
return 1;
}
...
You need root privileges for that (or CAP_SYS_RESOURCE
capability, I guess).
Linux kernel really returns EMFILE
for this case, check it here:
if (u->mq_bytes + mq_bytes < u->mq_bytes ||
u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
spin_unlock(&mq_lock);
/* mqueue_evict_inode() releases info->messages */
ret = -EMFILE;
goto out_inode;
}
The reason for EMFILE
here is probably that it's the most close error code from those specified in POSIX; EMFILE
is the only error code that reflects reaching a per-process limitation.
POSIX doesn't specify a more precise error code for RLIMIT_MSGQUEUE
because it is Linux-specific.
Posix Queues. Receive and Priorities
It's possible because you never unlink
your queue that you are unknowingly working with a previously created one. If the old queue was created with a message size larger than the msg_len parameter you are passing to mq_receive
, that would explain your "Message too long" (EMSGSIZE) errors.
Try deleting any existing queues before you run the program. If they aren't already mounted you can mount the queues like so:
sudo mkdir /dev/mqueue
sudo mount -t mqueue none /dev/mqueue
You can then perform normal file operations like ls /dev/mqueue
and rm /dev/mqueue/queue.txt
.
(Note: "queue.txt" is a pretty awful name. It's not a text file.)
Related Topics
Get Man Pages for Driver Functions
Why Do Es and Ds Zero Out Eventually on 64 Bit Kernel When Set to Tls Selectors
How to Connect to Docker Container from Localhost
Lapack/Blas/Openblas Proper Installation from Source - Replace System Libraries with New Ones
Difference Between "Cpu/Mem-Loads/Pp" and "Cpu/Mem-Loads/"
How to Make 'Docker Run' Inherit Ulimits
Ssl and Tkinter Not Present on Source Build of Python 3.5.2, Debian Linux
Ssh Agent Forwarding Inside Cron Jobs
Assembly Divisions and Floating Points
Linux Nasm Move a Value in Al Up to Ax
Sending Realtime Signal from a Kernel Module to User Space Fails
Hugo Version Not Updating to Latest