【问题标题】:Should I synchronize mq_timedreceive calls when performed by multiple threads?当由多个线程执行时,我应该同步 mq_timedreceive 调用吗?
【发布时间】:2012-03-20 04:14:52
【问题描述】:

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

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

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

提前致谢。

【问题讨论】:

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


    【解决方案1】:

    内核会为您进行锁定。

    看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->lock 保护的,所以两个线程不可能得到相同的消息。

    【讨论】:

    • 我浏览了文件ipc/mqueue.c,但我不太确定lock 是否确实阻止了消息发送给多个接收者。你能详细说明你的答案吗?
    【解决方案2】:

    这个手册页描述得很好:

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

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

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

    【讨论】:

      猜你喜欢
      • 2017-01-14
      • 2019-02-27
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 1970-01-01
      相关资源
      最近更新 更多