IPC 队列消息错误
IPC Queue msgsnd error
这是一个将消息发送到队列的简单程序,但输出为 "snd error"。
队列已创建。我用 ipcs -q 检查过。
我做错了什么?
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<stdlib.h>
struct msg{
int mtype;
char mtext[1024];
}snd;
void main()
{
int id;
if(id=msgget(1234,IPC_CREAT|0666)<0)
{
printf("ipc error");
}
else{
snd.mtype=1;
scanf("%[^\n]",snd.mtext);
getchar();
if(msgsnd(id,&snd,sizeof(snd.mtext),IPC_NOWAIT)<0){
printf("snd error");
}
else {
printf("msg snd");
}
}
}
What have i done wrong?
你检查了msgsnd
的return代码,很好,这意味着,你已经领先于很多程序员了。但是您还没有阅读 msgsnd
的整个手册,其中说明
RETURN VALUE
On failure both functions return -1 with errno indicating the error,
其中 errno
是重要部分。
当您进一步查看时,还有一个名为 ERRORS 的部分,它显示了可能出现的问题
ERRORS
When msgsnd() fails, errno will be set to one among the following
values:
EACCES The calling process does not have write permission on the
message queue, and does not have the CAP_IPC_OWNER capability.
EAGAIN The message can't be sent due to the msg_qbytes limit for the
queue and IPC_NOWAIT was specified in msgflg.
...
再往下,您会找到示例部分
EXAMPLE
The program below demonstrates the use of msgsnd() and msgrcv().
...
其中msgsnd
的用法显示了一个重要的习语:当发生错误并且在errno
中报告了特定错误时,此错误可能由perror
[=39打印=]
if (msgsnd(qid, (void *) &msg, sizeof(msg.mtext),
IPC_NOWAIT) == -1) {
perror("msgsnd error");
exit(EXIT_FAILURE);
}
perror
将显示一条消息,详细说明调用 msgsnd
时出现的错误。这也可以与任何其他系统调用一起使用。
根据手册 "Invalid argument" (EINVAL
) 表示
之一
EINVAL msqid was invalid, or msgsz was less than 0.
EINVAL (since Linux 3.14) msgflg specified MSG_COPY, but not IPC_NOWAIT.
EINVAL (since Linux 3.14) msgflg specified both MSG_COPY and MSG_EXCEPT.
因为你没有指定MSG_COPY
,错误一定是第一个。
msgsz
肯定大于0
- 所以一定是无效的msqid!
当你看
if(id = msgget(1234, IPC_CREAT | 0666) < 0)
您会看到 (id = msgget(...))
周围缺少括号。很可能msgget
returns一个值>0,所以msgget(...) < 0
为false,id会变成0(false),走else分支
因此,调用 msgsnd(0, ...)
很可能是错误的罪魁祸首。
要解决这个问题,请明确
id = msgget(1234, IPC_CREAT | 0666);
if (id < 0) {
...
} else {
...
}
或至少在作业周围加上括号
if ((id = msgget(1234, IPC_CREAT | 0666)) < 0) {
这是一个将消息发送到队列的简单程序,但输出为 "snd error"。 队列已创建。我用 ipcs -q 检查过。 我做错了什么?
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<stdlib.h>
struct msg{
int mtype;
char mtext[1024];
}snd;
void main()
{
int id;
if(id=msgget(1234,IPC_CREAT|0666)<0)
{
printf("ipc error");
}
else{
snd.mtype=1;
scanf("%[^\n]",snd.mtext);
getchar();
if(msgsnd(id,&snd,sizeof(snd.mtext),IPC_NOWAIT)<0){
printf("snd error");
}
else {
printf("msg snd");
}
}
}
What have i done wrong?
你检查了msgsnd
的return代码,很好,这意味着,你已经领先于很多程序员了。但是您还没有阅读 msgsnd
的整个手册,其中说明
RETURN VALUE
On failure both functions return -1 with errno indicating the error,
其中 errno
是重要部分。
当您进一步查看时,还有一个名为 ERRORS 的部分,它显示了可能出现的问题
ERRORS
When msgsnd() fails, errno will be set to one among the following values:EACCES The calling process does not have write permission on the message queue, and does not have the CAP_IPC_OWNER capability. EAGAIN The message can't be sent due to the msg_qbytes limit for the queue and IPC_NOWAIT was specified in msgflg.
...
再往下,您会找到示例部分
EXAMPLE
The program below demonstrates the use of msgsnd() and msgrcv().
...
其中msgsnd
的用法显示了一个重要的习语:当发生错误并且在errno
中报告了特定错误时,此错误可能由perror
[=39打印=]
if (msgsnd(qid, (void *) &msg, sizeof(msg.mtext),
IPC_NOWAIT) == -1) {
perror("msgsnd error");
exit(EXIT_FAILURE);
}
perror
将显示一条消息,详细说明调用 msgsnd
时出现的错误。这也可以与任何其他系统调用一起使用。
根据手册 "Invalid argument" (EINVAL
) 表示
EINVAL msqid was invalid, or msgsz was less than 0.
EINVAL (since Linux 3.14) msgflg specified MSG_COPY, but not IPC_NOWAIT.
EINVAL (since Linux 3.14) msgflg specified both MSG_COPY and MSG_EXCEPT.
因为你没有指定MSG_COPY
,错误一定是第一个。
msgsz
肯定大于0- 所以一定是无效的msqid!
当你看
if(id = msgget(1234, IPC_CREAT | 0666) < 0)
您会看到 (id = msgget(...))
周围缺少括号。很可能msgget
returns一个值>0,所以msgget(...) < 0
为false,id会变成0(false),走else分支
因此,调用 msgsnd(0, ...)
很可能是错误的罪魁祸首。
要解决这个问题,请明确
id = msgget(1234, IPC_CREAT | 0666);
if (id < 0) {
...
} else {
...
}
或至少在作业周围加上括号
if ((id = msgget(1234, IPC_CREAT | 0666)) < 0) {