今天有一同事问我,如果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
Code
1asmlinkage long
2sys_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
14long 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
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
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)
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
14long 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
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
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
1asmlinkage long
2sys_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
14long 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
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
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,所以会阻塞在这里,直到队列可用!