Как «изменить направление» очереди сообщений POSIX в Linux?

#c #posix #message-queue

Вопрос:

Я пытаюсь понять, как «перевернуть» одну очередь сообщений POSIX, чтобы обеспечить двустороннюю связь между клиентским и серверным процессом, используя только одну очередь сообщений POSIX (т. Е. Только один сегмент памяти за раз). По сути, это полудуплексная настройка, в которой поддерживается двусторонняя связь, но сообщения могут передаваться только в одном направлении одновременно.

Стандартный подход заключается в использовании одной очереди для клиента -gt; сервер и одной очереди для сервера -gt;gt; клиент, как показано ниже (это в основном мой текущий код).

Клиент:

 ... int read = mq_open("servertoclient", O_RDWR | O_CREAT, 0600, 0); int write = mq_open("clienttoserver", O_RDWR | O_CREAT, 0600, 0); char send_buffer[8192]; mq_send(write, send_buffer, 8192, 0); //send message to server char receive_buffer[8192]; mq_receive(read, receive_buffer, 8192, 0); //receive response from server mq_close(write); mq_close(read); mq_unlink("servertoclient"); mq_unlink("clienttoserver"); ...  

Сервер:

 ... int write = mq_open("servertoclient", O_RDWR | O_CREAT, 0600, 0); int read = mq_open("clienttoserver", O_RDWR | O_CREAT, 0600, 0); char send_buffer[8192]; mq_send(write, send_buffer, 8192, 0); //send message to client char receive_buffer[8192]; mq_receive(read, receive_buffer, 8192, 0); //receive response from client mq_close(write); mq_close(read); mq_unlink("servertoclient"); mq_unlink("clienttoserver"); ...  

Я ищу способ выполнить почти то же самое, но только с использованием одной очереди сообщений за раз, а не по одному для каждого направления одновременно. Единственная разница в том, что при использовании одной очереди одновременная отправка/получение не будет поддерживаться, что в моей ситуации нормально. Сервер и клиент будут использовать какой-то специальный «код», который сигнализирует об отмене очереди. Это похоже на радио, где вы говорите, затем отпускаете кнопку, и приемник подает звуковой сигнал, давая им знать, что вы закончили говорить. Затем вы слушаете сообщение получателя, пока ваше радио не подаст звуковой сигнал. Но отправитель и получатель никогда не смогут разговаривать друг с другом.

Что-то в этом роде:

Клиент:

 open a single queue with mq_open for writing to the server send some data send a special message notifying the server that the queue is to be reversed prepare queue for reading (not sure how to do this) read data from server until the 'reverse' message is received, then revert queue to write ... keep going like this until a terminating message is received or client exits  unlink the queue  

Сервер:

 open a single queue with mq_open for reading from client read in data if the terminating message is read,   prepare queue for writing to client send data and finish by sending the special 'reverse' message prepare queue for reading ... keep going like this until a terminating message is received or server exits  unlink the queue  

Клиент всегда будет инициировать первое сообщение, поэтому, например, никогда не возникнет опасности, что сервер захочет отправить сообщение изначально.

Я не открыт для использования каких-либо других методов межпроцессной связи (таких как общая память, очереди sysv, каналы, tcp/udp и т.д.).

Комментарии:

1. Простите, что спрашиваю, но почему это так важно для вас?

2. @PaulSanders Я пытаюсь сократить нагрузку на память вдвое, особенно когда к серверу подключено много клиентских процессов. При использовании метода с двумя очередями использование памяти было довольно высоким при таком количестве очередей (в 2 раза больше очередей, чем клиентов). Если возможно, я бы предпочел использовать только одну очередь на соединение клиент-сервер для экономии ресурсов.

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

4. Я прошу прощения, если я не был ясен в первоначальном вопросе. Я бы сделал свою собственную реализацию в качестве последнего средства, но я строго ограничен очередью POSIX в соответствии со стандартами. Если бы у меня не было этого ограничения, я бы определенно использовал что-то вроде очереди SysV или сокета. Все, что мне нужно знать, — это как «обратить вспять» поток информации в очереди POSIX. Я возился с различными размещениями mq_close и mq_open, но все они привели к ошибке сегментации или какому-то коду ошибки (чаще всего EMFILE и EINTR). Кстати, ОС, на которой я это запускаю, — Ubuntu Linux.