我应该在多个线程执行时同步mq_timedreceive调用吗?

时间:2012-03-01 16:32:07

标签: c linux posix message-queue shared-memory

我在Linux上使用Posix消息队列。基本上,我有多个线程通过调用mq_timedreceive从同一队列接收消息。

如果同时运行多个线程并且队列不为空,我是否保证不会多次收到消息(即消息未被传递到多个线程)?

可以肯定的是,我可以将接收与互斥锁同步,但是如果可能的话我想避免这种锁定。我阅读了所有的手册页(man mq_overview(3)),但没有发现任何明确的内容。

提前致谢。

2 个答案:

答案 0 :(得分:3)

内核会为你锁定。

查看ipc / mqueue.c中的实现:

SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
                size_t, msg_len, unsigned int __user *, u_msg_prio,
                const struct timespec __user *, u_abs_timeout)
{    
    ...   
    struct mqueue_inode_info *info;
    ...
    filp = fget(mqdes);
    if (unlikely(!filp)) {
        ret = -EBADF;
        goto out;
    }

    inode = filp->f_path.dentry->d_inode;
    ...
    spin_lock(&info->lock);
    if (info->attr.mq_curmsgs == 0) {
        if (filp->f_flags & O_NONBLOCK) {
            spin_unlock(&info->lock);
...
    } else {
        msg_ptr = msg_get(info);

        inode->i_atime = inode->i_mtime = inode->i_ctime =
                            CURRENT_TIME;

        /* There is now free space in queue. */
        pipelined_receive(info);
        spin_unlock(&info->lock);
        ret = 0;
    }

每个mqueue都有一个自旋锁,在检查新消息之前获取它。

最后一个else(pipelined_receive)是消息出列的地方。这受info->锁保护,因此两个线程无法获得相同的消息。

答案 1 :(得分:2)

这个手册页很好地描述了它:

http://pubs.opengroup.org/onlinepubs/009604499/functions/mq_receive.html

  

如果有多个线程在消息到达空队列并且支持优先级调度选项时等待接收消息,则应选择等待时间最长的最高优先级的线程来接收消息。否则,未指定哪个等待线程接收消息。

这允许您使用POSIX消息队列来实现生产者/消费者线程。