Есть ли способ отправить EOF процессу, читающему очередь сообщений?
У меня есть один процесс отправки данных через очередь сообщений с msgsnd
, Еще один процесс чтения из очереди с msgrcv
, Процесс чтения должен ждать, пока у него не появятся все сообщения, прежде чем он сможет продолжить. Как я могу сказать, что все сообщения были отправлены?
То, как я это делал, - после того, как отправитель отправил все свои сообщения, он затем проверяет количество сообщений в очереди в цикле while. Когда больше нет сообщений, он закрывает очередь.
Это говорит процессу чтения, чтобы продолжать делать другие вещи. Это не кажется очень надежным, хотя. Много раз процесс отправки застревал в бесконечном цикле проверки состояния очереди.
Есть ли способ для меня просто отправить сообщение EOF и следить за процессом чтения? Тогда я мог бы просто отправить EOF и завершить процесс отправки.
1 ответ
Обычно получатель замечает, что отправитель закончил отправку, потому что он пытается получить следующее сообщение, а приемный вызов указывает, что для получения ничего не осталось. При связи через файловые дескрипторы (каналы, сокеты) закрытие - это то, как вы "отправляете EOF", и read
вызов возвращает 0 байтов. С очередями сообщений это немного отличается, потому что они основаны на сообщениях, а не на потоках, и часто бывает несколько отправителей.
Ты можешь позвонить msgctl
с командой IPC_RMID
, Это вызывает любое ожидание или последующий вызов msgrcv
(или же msgsnd
) возвращать -EIDRM
(-EINVAL
на некоторых системах BSD). Проблема с этим подходом состоит в том, что в очереди могут быть сообщения, ожидающие в очереди, которые получатель еще не прочитал, и поэтому мы потерялись.
Вместо этого, когда отправителю больше нечего делать, отправьте в очередь сообщение с надписью "Я закончил". В получателе, когда вы получите это сообщение, удалите очередь. Это хорошо работает, когда вы используете очередь между потоками одного процесса. Если существует несколько процессов, отправитель может умереть, не отправив сообщение о завершении.
То, как обрабатывать случай с несколькими процессами, будет зависеть от структуры вашего приложения и, в частности, от того, что процесс чтения хочет сделать, когда отправитель мертв. Один из способов обнаружить это - установить канал между отправителем и получателем. Пусть поток на ресивере прослушивает этот канал; если он обнаруживает конец файла, он может
- установить переменную, которая используется совместно с потоком, который вызывает
msgrcv
; - заглянуть в очередь (
msgctl
сIPC_STAT
); - если очередь пуста (
msg_qnum == 0
), убери это.