我正在unix系统上用C编写代码。我已经创建了一个消息队列服务器。每次我收到一条新消息时,我就会分叉,子进程将处理新客户端。服务器正在等待新的客户端。这是密码。
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:无效参数,而不是等待新消息。
发布于 2009-10-18 21:12:26
msgrcv确实有一个msgsz参数,但它不是struct my_msgbuf的大小,而是结构的mtext[]字段中的字节数。
我认为,您不应该直接使用struct msgbuf。用适当的空间定义自己的空间是正常的。按照您的方式,您的buf声明只分配了一个字节,然后代码告诉内核您有sizeof buf字节,但是没有。因此,代码被称为调用未定义的行为或UB。
这可能解释或不可能解释EINVAL,但我们应该总是修复已知的错误并重新测试,因为UB污染了进一步的分析。
发布于 2019-06-30 05:31:00
上面的代码很少有问题。首先在这里
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 (msqid, &buf, sizeof(buf), 1, 0);现在代码适用于第一次迭代,但是在第二次迭代中,msgrcv给出了以下错误- msgrcv:无效参数而不是等待新消息?
这是因为msgrcv()在fork()之前执行,如果父进程没有执行msgsnd()怎么办?
要解决这个问题,您应该将msgrcv()语句保留在子进程中。还在子进程和父进程内部运行for循环,而不是在子/父块之外运行。如:
struct my_msgbuf buf;
if((pid = fork())<0)
{
/* @TODO set the buf.mtype here */
perror("fork");
for(;;) /* use loop inside parent process to write into MQ continuously */
{
/* @TODO scan the data into buf.mtext */
/* @TODO msgsnd statement */
}
}
else
{
for(;;) /* use loop inside child process to read from MQ continuously */
{
if (msgrcv (msqid, &buf, sizeof (buf), 1, 0) == -1)
perror ("msgrcv");
printf("received data : %s\n", buf.mtext);
}
}https://stackoverflow.com/questions/1586006
复制相似问题