2017-05-29 103 views
0

所以程序就是这样工作的。有一个生产者和4个消费者。生产者生成6个随机数并通过消息队列将它们发送给4个消费者。每个消费者接收它们,并且在终止之前立即 ,应该通过另一个队列发送mayproduce = 0的一条消息; mayproduce是一个整数。消息队列不接受0作为参数

有问题的功能是:

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 

我使用的功能像这样送mayproduce

msgsnd(qid,&mayproduce,sizeof(int),0) 

当我编译它说: “无效参数”。

如果我改变mayproduce为其他号码,mayproduce = 2,程序工作正常。

有谁知道它不接受0作为参数的原因吗?

的代码示例:

mayproduce=2; // if I put 0 here it doesn't work 
if(msgsnd(msq2,&mayproduce,tamanho,0)<0) { 
    perror("\nConsumidor:Erro ao enviar a mensagem: "); 
    exit(1); 
} 
+1

显示完整的错误消息。完整的代码或至少是完整的代码片段。 –

+0

'mayproduce == 0'不像“将'mayproduce'设置为另一个数字”。这是将'mayproduce'设置为0或1的比较。由于缺乏MCVE而投票结束。 –

+0

是的@WeatherVane这是我的错误。我的意思是mayproduce = 0 – Ackerman

回答

1

msgsnd()文档状态:

The msgp argument is a pointer to a caller-defined 
    structure of the following general form: 

     struct msgbuf { 
      long mtype;  /* message type, must be > 0 */ 
      char mtext[1]; /* message data */ 
     }; 

的帮助页中,你需要阅读非常非常多了很多信息小心。

所以你不是真的应该发送一个指针到一个int。您应该创建自己的结构,其中1.成员的类型为long,并用作消息类型鉴别符,接收方可以查看它以确定它接收的消息类型。

您传递给msgsend()的大小是您发送的所有内容在mtype成员之后的大小。

当执行msgsnd(qid,&mayproduce,sizeof(int),0)会发生以下情况:

  • mayproduce INT被解释为在一个struct msgbufmtype构件,作为文档说,它不能为0
  • 的的sizeof(int)的说你除了long msgtype之外还会有一个int。但您的&mayproduce指针只是指向一个int,因此您可能还会从堆栈中抓取垃圾值。

你应该这样做:

struct MyMsg { 
    long mtype; 
    int mayproduce; 
}; 

struct MyMsg msg; 
msg.mtype = 1; //or whatever you want > 0 
msg.mayproduce = ....; //whatever you want to send. 
size_t msgsize = sizeof(struct MyMsg) - sizeof(long); 

msgsnd(msq2,&msg,msgsize,0); 
+0

是不是计算'msgsize'容易被填充?如果(比如说)long是8字节而int是4,那么sizeof(struct MyMsg)可能是16,并且结束填充。这并不能保证,但这对于一个对齐的64位体系结构来说是典型的。因此它会计算出'msgsize = sizeof(struct MyMsg) - offsetof(struct MyMsg,mayproduce);'as 8.因此会发送陷阱表达式。如果接收者仅查看前4个字节,但不是“msgsize = sizeof(int)”正确答案,那么这不一定有害? – Persixty

+0

@Persixty为什么会发送陷阱表达式?我们分配了一个struct MyMsg,并且告诉msgsnd()发送从'mayproduce'开始的所有8个字节到最后,包括填充(如果有的话)。我怀疑大小的计算不是很正确,但是如果在'mtype'和'mayproduce'之间有填充,会在接收端读入同一个结构时产生问题。这个计算可能只是'sizeof(struct MyMsg) - sizeof(long)' – nos

+0

也许我滥用术语陷阱表达式......我的意思是(在64位对齐的体系结构上)将导致8字节发送时只有4个是有意义的。将另外4个字节复制到结构中将会很好。 如果(比如说)成员类型对齐> long,并且在成员之前存在填充,它甚至无法帮助,因为我看不到'msgsend'除了复制'sizeof(long) + msgsz'左右。 安全的(但不合法的)代码将与'sizeof(struct MyMsg)-sizeof(long)'一起传递,并且传递所有的填充,我们确信'mtype'在'struct'的开始处 – Persixty