我在unix系统上用C编写代码。我创建了一个消息队列服务器。每次收到新消息时,我都会fork,子进程会处理新客户端。服务器等待新客户端。这是代码。
for (;;)
{
struct my_msgbuf buf;
if (msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0) == -1)
perror ("msgrcv");
if((pid = fork())<0)
perror("fork");
if(pid==0)
{
//child code
}
}
现在代码适用于第一次迭代,但在第二次迭代时,msgrcv会出现以下错误 - msgrcv:参数无效,而不是等待新消息。
答案 0 :(得分:0)
msgrcv
确实采用msgsz
参数,但它不是struct my_msgbuf
的大小,而是结构的mtext[]
字段中的字节数。
我认为你不应该直接使用struct msgbuf
。用适当的空间定义自己的内容是很正常的。你拥有它的方式,你的buf
声明只分配1个字节,然后代码告诉内核你有sizeof buf
个字节,而你没有。因此,代码被称为调用 Undefined Behavior 或UB。
这可能会或可能不会解释EINVAL
但是应该总是修复已知的错误并重新测试,因为UB会进一步分析...
答案 1 :(得分:0)
以上代码几乎没有问题。首先在这里
reshape
第二个自变量msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0)
是错误的,因为预期过程不仅会收到&(buf.mtype)
,而且还会收到完整的buf
。如果buf.mtype
看起来像
struct my_msgbuf
然后struct my_msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
应该看起来像
msgrcv()
现在,代码适用于第一次迭代,但适用于第二次迭代 msgrcv给出以下错误-msgrcv:无效参数 等待新消息?
这是因为msgrcv (msqid, &buf, sizeof(buf), 1, 0);
在msgrcv()
之前执行,如果父进程未执行fork()
会怎样?
要解决此问题,您应在子进程中保留msgsnd()
语句。还要在子进程和父进程内部而不是子/父块外部运行for循环。对于例如
msgrcv()