[每日一点]msgsnd函数代码跟踪

今天有一同事问我,如果msgsnd函数的最后一个flag如果直接置0,调用该函数会是什么结果!

我不太清楚是怎样的,还是直接看代码:

msgsnd是一个系统调用,所以它在glibc中只是一个桩函数:
\glibc\glibc-2.4.src\sysvipc\msgsnd.c
int
msgsnd (msqid, msgp, msgsz, msgflg)
     int msqid;
     const void *msgp;
     size_t msgsz;
     int msgflg;
{
  __set_errno (ENOSYS);
  return -1;
}

stub_warning (msgsnd)

而在内核中的实现函数:

~\kernel\linux-2.6.21.1.src\ipc\msg.c

ContractedBlock.gif ExpandedBlockStart.gif
ContractedBlock.gif ExpandedBlockStart.gif Code
  1asmlinkage long
  2sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
  3ExpandedBlockStart.gifContractedBlock.gif{
  4 long mtype;
  5
  6 if (get_user(mtype, &msgp->mtype))
  7  return -EFAULT;
  8 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
  9}

 10
 11
 12
 13
 14long do_msgsnd(int msqid, long mtype, void __user *mtext,
 15  size_t msgsz, int msgflg)
 16ExpandedBlockStart.gifContractedBlock.gif{
 17 struct msg_queue *msq;
 18 struct msg_msg *msg;
 19 int err;
 20 struct ipc_namespace *ns;
 21
 22 ns = current->nsproxy->ipc_ns;
 23
 24 if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 25  return -EINVAL;
 26 if (mtype < 1)
 27  return -EINVAL;
 28
 29 msg = load_msg(mtext, msgsz);
 30 if (IS_ERR(msg))
 31  return PTR_ERR(msg);
 32
 33 msg->m_type = mtype;
 34 msg->m_ts = msgsz;
 35
 36 msq = msg_lock(ns, msqid);
 37 err = -EINVAL;
 38 if (msq == NULL)
 39  goto out_free;
 40
 41 err= -EIDRM;
 42 if (msg_checkid(ns, msq, msqid))
 43  goto out_unlock_free;
 44
 45ExpandedSubBlockStart.gifContractedSubBlock.gif for (;;) {
 46  struct msg_sender s;
 47
 48  err = -EACCES;
 49  if (ipcperms(&msq->q_perm, S_IWUGO))
 50   goto out_unlock_free;
 51
 52  err = security_msg_queue_msgsnd(msq, msg, msgflg);
 53  if (err)
 54   goto out_unlock_free;
 55
 56  if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
 57ExpandedSubBlockStart.gifContractedSubBlock.gif    1 + msq->q_qnum <= msq->q_qbytes) {
 58   break;
 59  }

 60
 61ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* queue full, wait: */
 62ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msgflg & IPC_NOWAIT) {
 63   err = -EAGAIN;
 64   goto out_unlock_free;
 65  }

 66  ss_add(msq, &s);
 67  ipc_rcu_getref(msq);
 68  msg_unlock(msq);
 69  schedule();
 70
 71  ipc_lock_by_ptr(&msq->q_perm);
 72  ipc_rcu_putref(msq);
 73ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msq->q_perm.deleted) {
 74   err = -EIDRM;
 75   goto out_unlock_free;
 76  }

 77  ss_del(&s);
 78
 79ExpandedSubBlockStart.gifContractedSubBlock.gif  if (signal_pending(current)) {
 80   err = -ERESTARTNOHAND;
 81   goto out_unlock_free;
 82  }

 83 }

 84
 85 msq->q_lspid = current->tgid;
 86 msq->q_stime = get_seconds();
 87
 88ExpandedSubBlockStart.gifContractedSubBlock.gif if (!pipelined_send(msq, msg)) {
 89ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* noone is waiting for this message, enqueue it */
 90  list_add_tail(&msg->m_list, &msq->q_messages);
 91  msq->q_cbytes += msgsz;
 92  msq->q_qnum++;
 93  atomic_add(msgsz, &msg_bytes);
 94  atomic_inc(&msg_hdrs);
 95 }

 96
 97 err = 0;
 98 msg = NULL;
 99
100out_unlock_free:
101 msg_unlock(msq);
102out_free:
103 if (msg != NULL)
104  free_msg(msg);
105 return err;
106}

107
108
Code
  1asmlinkage long
  2sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
  3ExpandedBlockStart.gifContractedBlock.gif{
  4 long mtype;
  5
  6 if (get_user(mtype, &msgp->mtype))
  7  return -EFAULT;
  8 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
  9}
 10
 11
 12
 13
 14long do_msgsnd(int msqid, long mtype, void __user *mtext,
 15  size_t msgsz, int msgflg)
 16ExpandedBlockStart.gifContractedBlock.gif{
 17 struct msg_queue *msq;
 18 struct msg_msg *msg;
 19 int err;
 20 struct ipc_namespace *ns;
 21
 22 ns = current->nsproxy->ipc_ns;
 23
 24 if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 25  return -EINVAL;
 26 if (mtype < 1)
 27  return -EINVAL;
 28
 29 msg = load_msg(mtext, msgsz);
 30 if (IS_ERR(msg))
 31  return PTR_ERR(msg);
 32
 33 msg->m_type = mtype;
 34 msg->m_ts = msgsz;
 35
 36 msq = msg_lock(ns, msqid);
 37 err = -EINVAL;
 38 if (msq == NULL)
 39  goto out_free;
 40
 41 err= -EIDRM;
 42 if (msg_checkid(ns, msq, msqid))
 43  goto out_unlock_free;
 44
 45ExpandedSubBlockStart.gifContractedSubBlock.gif for (;;) {
 46  struct msg_sender s;
 47
 48  err = -EACCES;
 49  if (ipcperms(&msq->q_perm, S_IWUGO))
 50   goto out_unlock_free;
 51
 52  err = security_msg_queue_msgsnd(msq, msg, msgflg);
 53  if (err)
 54   goto out_unlock_free;
 55
 56  if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
 57ExpandedSubBlockStart.gifContractedSubBlock.gif    1 + msq->q_qnum <= msq->q_qbytes) {
 58   break;
 59  }
 60
 61ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* queue full, wait: */
 62ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msgflg & IPC_NOWAIT) {
 63   err = -EAGAIN;
 64   goto out_unlock_free;
 65  }
 66  ss_add(msq, &s);
 67  ipc_rcu_getref(msq);
 68  msg_unlock(msq);
 69  schedule();
 70
 71  ipc_lock_by_ptr(&msq->q_perm);
 72  ipc_rcu_putref(msq);
 73ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msq->q_perm.deleted) {
 74   err = -EIDRM;
 75   goto out_unlock_free;
 76  }
 77  ss_del(&s);
 78
 79ExpandedSubBlockStart.gifContractedSubBlock.gif  if (signal_pending(current)) {
 80   err = -ERESTARTNOHAND;
 81   goto out_unlock_free;
 82  }
 83 }
 84
 85 msq->q_lspid = current->tgid;
 86 msq->q_stime = get_seconds();
 87
 88ExpandedSubBlockStart.gifContractedSubBlock.gif if (!pipelined_send(msq, msg)) {
 89ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* noone is waiting for this message, enqueue it */
 90  list_add_tail(&msg->m_list, &msq->q_messages);
 91  msq->q_cbytes += msgsz;
 92  msq->q_qnum++;
 93  atomic_add(msgsz, &msg_bytes);
 94  atomic_inc(&msg_hdrs);
 95 }
 96
 97 err = 0;
 98 msg = NULL;
 99
100out_unlock_free:
101 msg_unlock(msq);
102out_free:
103 if (msg != NULL)
104  free_msg(msg);
105 return err;
106}
107
108

security_msg_queue_msgsnd函数是调用一个钩子函数,之后没有对flag进行处理。所以,flag只在这个函数中有效:

即,只有在队列满,且标志位与IPC_NOWAIT或时不为0,则返回错误,否则没有什么影响。如果为0时,与IPC_NOWAIT取或运算显然为不0,所以会阻塞在这里,直到队列可用!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值