当前位置:  技术问答>linux和unix

多个进程,同时读写消息队列,是否会冲突

    来源: 互联网  发布时间:2016-10-27

    本文导语:  多个进程,同时读写消息队列,是否会冲突。 请问这个多个进程同时写消息队列,是否需要用mutex来进行同步啊。 | OK!来总结一下这个问题,因为我也不确定,所以写的东西未必正确,错误...

多个进程,同时读写消息队列,是否会冲突。
请问这个多个进程同时写消息队列,是否需要用mutex来进行同步啊。

|
OK!来总结一下这个问题,因为我也不确定,所以写的东西未必正确,错误的地方,尽管拍砖!

我的内核代码是2.6.29.1。

// 先看msgsnd()函数,它通过系统调用接口界面,进入内核执行,代码如下:
SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
int, msgflg)
{
long mtype;

if (get_user(mtype, &msgp->mtype))
return -EFAULT;
return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
}
// 接下来看do_msgsnd()部分的代码,如下:
long do_msgsnd(int msqid, long mtype, void __user *mtext,
size_t msgsz, int msgflg)
{
struct msg_queue *msq;
struct msg_msg *msg;
int err;
struct ipc_namespace *ns;

ns = current->nsproxy->ipc_ns;

if (msgsz > ns->msg_ctlmax || (long) msgsz q_perm, S_IWUGO))
goto out_unlock_free;

err = security_msg_queue_msgsnd(msq, msg, msgflg);
if (err)
goto out_unlock_free;

if (msgsz + msq->q_cbytes q_qbytes &&
1 + msq->q_qnum q_qbytes) {
break;
}

/* queue full, wait: */
if (msgflg & IPC_NOWAIT) {
err = -EAGAIN;
goto out_unlock_free;
}
ss_add(msq, &s);
ipc_rcu_getref(msq);
msg_unlock(msq);
schedule();

ipc_lock_by_ptr(&msq->q_perm);
ipc_rcu_putref(msq);
if (msq->q_perm.deleted) {
err = -EIDRM;
goto out_unlock_free;
}
ss_del(&s);

if (signal_pending(current)) {
err = -ERESTARTNOHAND;
goto out_unlock_free;
}
}

msq->q_lspid = task_tgid_vnr(current);
msq->q_stime = get_seconds();

if (!pipelined_send(msq, msg)) {
/* noone is waiting for this message, enqueue it */
list_add_tail(&msg->m_list, &msq->q_messages);
msq->q_cbytes += msgsz;
msq->q_qnum++;
atomic_add(msgsz, &ns->msg_bytes);
atomic_inc(&ns->msg_hdrs);
}

err = 0;
msg = NULL;

out_unlock_free:
msg_unlock(msq);
out_free:
if (msg != NULL)
free_msg(msg);
return err;
}
// 在这段代码中,请注意临近入口位置的这个函数msg_lock_check(),我们跟进,看一下这个lock是如何check
// 的,代码如下:
static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
int id)
{
struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);

if (IS_ERR(ipcp))
return (struct msg_queue *)ipcp;

return container_of(ipcp, struct msg_queue, q_perm);
}
// ipc_lock_check()是一个能够check所有IPC object同步信息的函数,它的定义如下:
struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
{
struct kern_ipc_perm *out;

out = ipc_lock(ids, id);
if (IS_ERR(out))
return out;

if (ipc_checkid(out, id)) {
ipc_unlock(out);
return ERR_PTR(-EIDRM);
}

return out;
}
// 这里的ipc_lock()是至关重要的地方!通过这个函数的注释,也能明白它的作用了:
/**
 * ipc_lock - Lock an ipc structure without rw_mutex held
 * @ids: IPC identifier set
 * @id: ipc id to look for
 *
 * Look for an id in the ipc ids idr and lock the associated ipc object.
 *
 * The ipc object is locked on exit.
 */

struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
{
struct kern_ipc_perm *out;
int lid = ipcid_to_idx(id);

rcu_read_lock();
out = idr_find(&ids->ipcs_idr, lid);
if (out == NULL) {
rcu_read_unlock();
return ERR_PTR(-EINVAL);
}

spin_lock(&out->lock);

/* ipc_rmid() may have already freed the ID while ipc_lock
 * was spinning: here verify that the structure is still valid
 */
if (out->deleted) {
spin_unlock(&out->lock);
rcu_read_unlock();
return ERR_PTR(-EINVAL);
}

return out;
}

OK。至此分析完了一个msgsnd()的实现部分,也就是说内核内部已经为我们解决了同步问题了。不需要用户再去care这个问题了。msgrcv()的实现部分也是一样的道理。

|
sun的mq_receive函数的man page:

If more than one process (or thread) is waiting to receive a message when a message arrives at an empty queue, then the process of highest priority that has been waiting the longest is selected to receive the message. 



ms_send的man page:
If more than one thread is waiting to send when space becomes available in the message queue, then the thread of the highest priority which has been waiting the longest is unblocked to send its message. Otherwise, it is unspecified which waiting thread is unblocked. If the specified message queue is full and O_NONBLOCK is set in the message queue description associated with mqdes, the message is not queued and mq_send() returns an error.


看起来从应用层面是不用管理冲突的。

    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 怎么启动一个进程会在进程列表中显示出多个同名进程?
  • 请教如何编程实现父进程产生多个子进程
  • 一个进程中的多个线程不会被调度到一台机器中的多个cup并行执行吗?
  • 多个进程共用一个信号量,如果某个进程死掉,此时又将信号量锁定,其它进程就死掉,有什么办法可以解决这一问题
  • 多个同名进程的问题--急解决
  • 请教POSIX问题:一个进程中,可以有多个互斥锁麽?
  • 诸如httpd那样的服务,一次开多个进程,每个进程都监听同一个端口,但是一个端口怎么绑定多次呢?
  • 请问大虾们,同一串口能否被多个进程同时操作?
  • spawn-fcgi是如何做到让多个fastcgi进程监听同一端口的?
  • 怎么让多个进程共用一个socket
  • 如果有多个telnet登录,会不会有相同的进程号?
  • 问一个shell问题?怎样杀死多个进程。
  • 提问:如何控制多个进程?
  • 如何在多个进程之间共享一个磁盘文件?
  • 多个进程同时写一个管道会不会有问题???
  • 一个进程分离出多个线程后cpu时间分配问题
  • 如何在一个程序中同时启动多个进程执行不同的命令?
  • 如果父进程有多个线程,那么它的子进程也该拥有这些线程
  • 当多个进程同时进行打印输出时的问题
  • 如何等待多个子进程返回
  • Uploadify 'uploadify.php'存在多个输入验证漏洞
  • 我写了个linux下的网络程序,程序在多个电脑间通信,但是我没有多个电脑,怎么调试这样的程序啊?
  • PHP 'ext/soap/php_xml.c'不完整修复存在多个任意文件泄露漏洞
  • [提问]Linux下如何把多个.a文件编译一个.so文件,或者把多个.so文件编译成一个.so文件
  • linux下grep命令实现查找多个关键字(与关系和或关系)
  • 一个物理服器一个公网IP,多个虚拟机,多个域名
  • 多jdk环境下安装多个tomcat冲突解决配置方法
  • Apache + tomact 配多个域名 对 多个目录。
  • vim管理多个文件
  • 一个LINUX的驱动程序中,能不能注册多个中断?
  • 300分!查错,解决多个生产者和多个消费者问题 高手进!分不够想法子再加!


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3