Ограничения очереди сообщений Centos System V IPC
[Хотя я работаю в Perl, я считаю, что этот вопрос относится к API-интерфейсам и ограничениям IPC Linux System V, а не к чему-то, специфичному для Perl.]
У меня есть две машины Centos, каждая с CentOS Linux версии 7.9.2009 (Core).
У меня есть программа, которая разветвляет дочерний элемент, а затем использует сообщения System V IPC для связи с дочерним элементом, дочерний элемент готовит ответы и отправляет их родителю.
На одной машине мы видим ожидаемое поведение. Дочерний элемент создает пакеты сообщений, родительский их потребляет. Иногда дочерний элемент работает немного быстрее, чем родительский, и поэтому может заполнить очередь, затем дочерний элемент ждет, пока родительский элемент не получит несколько сообщений и продолжит работу.
Мы можем проверить размеры очередей с помощью ipcs -q и увидеть, что лимит по умолчанию в 10 сообщений в очереди иногда достигается, дочерний процесс приостанавливается, а затем мы видим, что очередь пуста, как и ожидалось.
Мы считаем, что ограничения очереди указаны в файлах /proc/sys/fs/mqueue/ и, например, msg_max равен ожидаемому значению 10. Эти значения идентичны на обеих машинах.
Мы также можем просмотреть пользовательские ограничения, относящиеся к очереди, с помощью ulimit -q и увидеть значение, превышающее 800000 байт на обеих машинах.
Загадка в том, что на нашей второй машине мы видим, как ребенок записывает в очередь три сообщения, пытается написать четвертое и ждет — мы намеренно не установили таймаут. Это как если бы автор записи считал, что очередь заполнена, хотя ipcs -q показывает в очереди только 3 элемента. На данный момент родитель еще не пытается прочитать сообщения.
------ Message Queues --------
key msqid owner perms used-bytes messages
0x0000002a 1474560 dave 600 15020 3
Вопрос: что, кроме переполнения очереди, может привести к приостановке msgsnd()? Пауза, кажется, продолжается бесконечно, ребенок продолжает, когда родитель становится активным и читает какие-то сообщения.
У нас есть много машин, на которых этот код работает без проблем. На трех новых машинах он не работает. Предположительно, существует какая-то специфичная для среды функция, которая взаимодействует с нашим кодом?
Код Perl использует тонкую библиотеку над системными вызовами (подробности опущены).
$mQueue = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR | S_IWUSR);
msgsnd( $mQueue, pack("l! a*", length($msg), $msg);
1 ответ
Проблема заключалась в том, что максимальный размер очереди по умолчанию был установлен на низкое значение.
Эту калибровку можно просмотреть с помощью опции -l для ipcs.
ipcs -q -l
------ Messages Limits --------
max queues system wide = 3671
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
Соответствующая настройка ядра хранится в
/proc/sys/kernel/msgmnb
и может быть изменен (как root) с помощью команды
sysctl -w kernel.msgmnb=65536
kernel.msgmnb = 65536