select(), posix 消息队列和 Linux 中的多线程



我遇到了有关消息队列的问题:

  • 我已经使用 mq_timedreceive() 在abs_timeout时间内获取消息队列。但此功能受系统时间 (CLOCK_REALTIME) 的影响。我的意思是,当系统时间发生变化时,abs_timeout(绝对时间)不再正确。

为了解决这个问题,我意识到它应该更改为CLOCK_MONOTOIC时钟。但是在 Linux 中,没有办法(我搜索并发现 QNX 支持这种机制)。

最后,我将 select() 和 mq_timereceive 与 NO_WAIT 结合起来。+ select():使用相对时间,因此不受系统时间变化的影响。超时后,我会得到带有 mq_timereceive() 的消息队列,当然绝对时间 = 0;

但我的问题是:如果系统有许多线程正在等待相同的消息队列(通过使用 select()),

  • 如果将消息发送到消息队列,则会唤醒并运行所有等待线程。所以这是错误的。
  • 也许线程(不是第一个等待线程)首先唤醒并收到此消息。
  • 我的预期是只有第一个等待线程应该被唤醒,它会得到消息,而其他人仍然阻止。请帮忙。

看起来你有几个问题:

  1. 等待超时不受时钟调整影响的消息队列。在Linux中,以下API支持时钟(CLOCK_REALTIMECLOCK_MONOTONIC等)选择:timerfd_createtimer_create。将这些与mq_timedreceive集成的一种方法是让timer_create触发中断mq_timedreceive的信号。

  2. 将 POSIX 消息队列上的等待与 select 集成。最直接的方法是使用mq_notify使其在新消息可用时传递信号,从而使select呼叫返回-1并将errno设置为 EINTR

  3. 公平排队,以便第一个服务员收到下一条消息。使用 POSIX 消息队列,如果等待线程在 mq_receive 中被阻止,则可能是可能的。否则,下一条可用消息将传递到首先调用mq_receive线程。

对于同一进程的线程之间的消息传递,另一种方法是让管道充当消息指针队列。也就是说,生产者线程创建一个消息并将指向它的指针写入管道(即不需要序列化整个消息,因为消息接收者位于同一进程中并且有权访问进程地址空间)。任何使用者线程都可以使用 select 在管道上等待,然后读取指向消息的指针。但是,如果多个线程在同一管道上等待,则它们都会被唤醒,但只有一个线程会从管道中读取消息指针。

最新更新