今天有一同事问我,如果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
1
asmlinkage long2
sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)3


{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

14
long do_msgsnd(int msqid, long mtype, void __user *mtext,15
size_t msgsz, int msgflg)16


{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

45

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 &&57

1 + msq->q_qnum <= msq->q_qbytes)
{58
break;59
}60

61

/**//* queue full, wait: */62

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);73

if (msq->q_perm.deleted)
{74
err = -EIDRM;75
goto out_unlock_free;76
}77
ss_del(&s);78

79

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

88

if (!pipelined_send(msq, msg))
{89

/**//* 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

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

108

1
asmlinkage long2
sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)3


{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

14
long do_msgsnd(int msqid, long mtype, void __user *mtext,15
size_t msgsz, int msgflg)16


{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

45

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 &&57

1 + msq->q_qnum <= msq->q_qbytes)
{58
break;59
}60

61

/**//* queue full, wait: */62

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);73

if (msq->q_perm.deleted)
{74
err = -EIDRM;75
goto out_unlock_free;76
}77
ss_del(&s);78

79

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

88

if (!pipelined_send(msq, msg))
{89

/**//* 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

100
out_unlock_free:101
msg_unlock(msq);102
out_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,所以会阻塞在这里,直到队列可用!