Как найти ожидающих читателей / писателей для Очередей сообщений Linux System V?

Мне поручено портировать некоторый код C/C++, который использует очереди System V, из HP-UX в Red Hat Linux (SVr4).

Большинство вызовов были переведены слишком хорошо, но у меня возникли трудности с одной конкретной проблемой, связанной с обнаружением ожидающих читателей и писателей в заданной очереди.

На HP можно использовать msgctl(IPC_STAT) чтобы получить структуру msqid_ds с подробной информацией о данной очереди.

Среди деталей в этой структуре короткое значение msqid_ds.msg_perm.mode, который использует младшие 9 бит, чтобы указать права доступа для пользователя / группы / других.

Однако в HP старшие 7 бит хранят другую информацию о состоянии, которая включает флаги, следующие за двумя флагами:

#define MSG_QWAIT       00001   /* a writer is waiting on qp->msg_cbytes */
#define MSG_FWAIT       00002   /* a writer is waiting on msgfp */

Это позволяет проверить, например, (msqid.msg_perm.mode & (MSG_RWAIT | MSG_WWAIT)) чтобы увидеть, есть ли читатели или писатели заблокированы в очереди.

Поскольку я портирую на Linux, очевидно, что эта возможность не одинакова. Определения для этих флагов не существуют, и значение msqid_ds.msg_perm.mode явно отсутствует старшая битовая информация.

Но, безусловно, есть операции с ядром, в которых поддерживаются читатели и составители этих очередей. Я надеюсь, что какая-то операция может быть вызвана для обнаружения этой информации.

1 ответ

Решение

Насколько я могу судить, Linux не имеет средств для доступа к пользователям, с помощью которых можно получить нужную вам информацию. POSIX также не определяет никаких таких средств (даже для очередей сообщений POSIX). Конечно, вы правы в том, что ядро ​​должно поддерживать состояние очереди сообщений, но я не вижу существующего механизма, с помощью которого эта информация может запрашиваться из пользовательского пространства. Если вы не хотите писать драйвер для ядра, я думаю, что ваш порт потребует более глубоких изменений, чем вы ожидали.

Но это не обязательно плохо в долгосрочной перспективе. Можно ожидать, что адаптация вашего кода таким образом, чтобы он опирался только на стандартные средства, а не на расширения поставщика, сделает его более надежным, более обслуживаемым и более переносимым. В зависимости от того, что пытается сделать унаследованный код, вы можете даже получить более совершенный дизайн в уязвимой области.

Подумайте, например, почему программа хочет получить информацию, о которой идет речь, и что она будет с ней делать. Я вижу только одну вескую причину: тест выполняется процессом / потоком как часть механизма сброса давления, при котором некоторые сообщения отбрасываются, если очередь задыхается от слишком большого / слишком большого количества сообщений. Любая другая причина, которую я рассмотрел, либо плохо продумана, либо лучше обслуживается с помощью неблокирующих отправлений и / или приемов. Если причина вашей программы в этой последней группе, то есть лучший способ сделать то, что она пытается сделать.

Даже если целью является вышеуказанное снятие давления, имейте в виду, что любая информация, которую вы получаете о переходном состоянии очереди сообщений, может оказаться устаревшей до того, как программа ее получит. Все заблокированные отправители могли успешно продолжить работу до того, как ваша программа обработает полученную информацию, и новые попытки отправки сообщений могут быть заблокированы. Это, возможно, понятное ограничение, но оно должно служить основой вашей стратегии по снижению давления. В этом случае у вас есть по крайней мере эти альтернативы:

  • Вместо того, чтобы пытаться определить, заблокированы ли какие-либо отправители, определите, находится ли очередь в своем объеме. Вы можете определить из стандарта struct msqid_ds текущее и максимальное количество сообщений в очереди. Вы также можете определить максимальное количество байтов, которое может вместить очередь, хотя стандартного способа определения текущего числа байтов в очереди не существует. (Тем не менее, существует специфический для Linux способ, если вы остаетесь очарованными расширениями вендоров.)

  • Проверьте, не заблокирована ли очередь, попытавшись отправить ей сообщение (используя неблокирующую отправку). В случае успеха немедленно удалите сообщение снова. Вы можете использовать тип сообщения, чтобы отличить эти сообщения от других приложений. При некотором сотрудничестве с другими получателями вы можете использовать тип сообщения, чтобы ни один другой получатель не получил эти проверочные сообщения.

Другие вопросы по тегам