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

时间:2016-04-24 10:03:57

标签: linux multithreading

我遇到了有关邮件队列的问题:

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

看起来你有几个问题:

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

  2. 使用select集成等待POSIX消息队列。最直接的方法是使用mq_notify在新消息可用时发送信号,从而将select调用返回-1errno设置为EINTR

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

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