我遇到了有关消息队列的问题:
- 我已经使用 mq_timedreceive() 在abs_timeout时间内获取消息队列。但此功能受系统时间 (CLOCK_REALTIME) 的影响。我的意思是,当系统时间发生变化时,abs_timeout(绝对时间)不再正确。
为了解决这个问题,我意识到它应该更改为CLOCK_MONOTOIC时钟。但是在 Linux 中,没有办法(我搜索并发现 QNX 支持这种机制)。
最后,我将 select() 和 mq_timereceive 与 NO_WAIT 结合起来。+ select():使用相对时间,因此不受系统时间变化的影响。超时后,我会得到带有 mq_timereceive() 的消息队列,当然绝对时间 = 0;
但我的问题是:如果系统有许多线程正在等待相同的消息队列(通过使用 select()),
- 如果将消息发送到消息队列,则会唤醒并运行所有等待线程。所以这是错误的。
- 也许线程(不是第一个等待线程)首先唤醒并收到此消息。
- 我的预期是只有第一个等待线程应该被唤醒,它会得到消息,而其他人仍然阻止。请帮忙。
看起来你有几个问题:
-
等待超时不受时钟调整影响的消息队列。在Linux中,以下API支持时钟(
CLOCK_REALTIME
,CLOCK_MONOTONIC
等)选择:timerfd_create
和timer_create
。将这些与mq_timedreceive
集成的一种方法是让timer_create
触发中断mq_timedreceive
的信号。 -
将 POSIX 消息队列上的等待与
select
集成。最直接的方法是使用mq_notify
使其在新消息可用时传递信号,从而使select
呼叫返回-1
并将errno
设置为EINTR
。 -
公平排队,以便第一个服务员收到下一条消息。使用 POSIX 消息队列,如果等待线程在
mq_receive
中被阻止,则可能是可能的。否则,下一条可用消息将传递到首先调用mq_receive
线程。
对于同一进程的线程之间的消息传递,另一种方法是让管道充当消息指针队列。也就是说,生产者线程创建一个消息并将指向它的指针写入管道(即不需要序列化整个消息,因为消息接收者位于同一进程中并且有权访问进程地址空间)。任何使用者线程都可以使用 select
在管道上等待,然后读取指向消息的指针。但是,如果多个线程在同一管道上等待,则它们都会被唤醒,但只有一个线程会从管道中读取消息指针。