【问题标题】:Message queue between parent and child causes invalid arguments in msgsnd父子之间的消息队列导致 msgsnd 中的参数无效
【发布时间】:2015-12-17 05:17:55
【问题描述】:

该过程创建 n 个孩子(n 个从标准输入读取),每个孩子必须每 2 秒后向父母发送一条消息,然后父母将收到的每条消息发送给所有孩子。我正在使用 2 个消息队列:一个是所有孩子都将消息发送给父母,另一个是父母发送消息并且每个孩子都阅读。每个孩子在成功发送或接收后打印其 pid 和从 msg 队列接收到的数据(数据只是一个随机数)。 但是程序显示错误“msgsnd:无效参数”。 我已经进行了一些调试以检查传递的任何参数是否为空或无效,但事实并非如此。不,我有点卡住了,不确定如何继续。任何帮助将不胜感激。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>

typedef struct msgbuf {
    long    mtype;
    int     num;
} message_buf;

long n;
void sigalrm(int signo){
        alarm(5);
        n=n+2;
        printf("%ld seconds elapsed\n",n);
        }
int main(int argc,char *argv[]){
    int id1,id2;
    int msgflg = IPC_CREAT | 0666;
    key_t key1,key2;
    key1 = ftok ("test2.c", 'A');
    key2 = ftok ("test2.c", 'B');
    message_buf sbuf,rbuf;
    size_t buf_length=sizeof(int);

    time_t t;


        pid_t pid;
        int i,j,k,n;
        n=atoi(argv[1]);

        if ((id1 = msgget(key1, msgflg )) < 0) {
                perror("msgget");
            }
        else 
            printf("Queue 1 created\n");  

        if ((id2 = msgget(key2, msgflg )) < 0) {
                perror("msgget");
            }
        else 
             printf("Queue 2 created\n");        

        for(i=0;i<n;i++)    {
        pid = fork();
        if(pid==0)  {
        setpgid(getpid(),getppid());
        signal(SIGALRM, sigalrm);
        alarm(2);
        while(1)        {
                srand((unsigned)time(&t));
                sbuf.mtype = i;
                sbuf.num=rand()%50;

                if  (msgsnd(id1, &sbuf, buf_length,0) < 0) {
                        perror("msgsnd");
                }
                else    {
                printf("msg sending successful\n");
                printf("%ld\t%d\n",(long)getpid(),sbuf.num);
            }
        pause();
 // paused so that now parent can send the messages before children receive it

            for(j=0;j<n;j++)    {

            if (msgrcv(id2, &rbuf, buf_length, j, 0) < 0) {
                perror("msgrcv");
                }
            else    {
                printf("msg receiving successful\n");
                printf("%ld\t%d\n",(long)getpid(),sbuf.num);
            } 
        }

    }

}

else if(pid>0)  {


while(1)    {
sleep(3);
//sleeping so that children can first send the message
            if (msgrcv(id1, &rbuf, buf_length,0, IPC_NOWAIT) < 0) {
                perror("msgrcv");
                }
            else    {
                printf("msg receiving successful\n");

            sbuf.num=rbuf.num;
            sbuf.mtype=rbuf.mtype;
for(k=0;k<n;k++)    {
            if (msgsnd(id2, &sbuf, buf_length, IPC_NOWAIT) < 0) {
                perror("msgsnd parent\n");
                //exit(1);

            }
        }
    }
    }

}
}
}

输出:

Queue 1 created
Queue 2 created
msgsnd: Invalid argument
2 seconds elapsed
msgrcv: No message of desired type
msgrcv: No message of desired type
4 seconds elapsed
msgrcv: Interrupted system call
msgrcv: No message of desired type
6 seconds elapsed
msgrcv: Interrupted system call
msgrcv: No message of desired type
msgrcv: No message of desired type
8 seconds elapsed
msgrcv: Interrupted system call

(used ctrl+c here).

【问题讨论】:

  • 请您在哪个平台上使用哪个 C 实现编译这个?
  • 与您的问题完全无关,但无需重复srand(time(...))。只需在程序开始时执行一次就足够了。
  • @WhiteViking thnx 指出来。
  • @alk 我使用的是 ubuntu 14.04,C 版本是 gcc 4.9。

标签: c linux gcc fork message-queue


【解决方案1】:

根据msgsnd man page

... mtype 字段必须有一个严格正数 整数值。 ...

...

EINVAL

无效的 msqid 值,或 非正 mtype 值,或无效的 msgsz 值(小于 0 或大于系统值 MSGMAX)。

mtype 设置为零,您无法发送消息。

【讨论】:

    猜你喜欢
    • 2017-08-25
    • 2014-06-23
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2011-02-21
    • 1970-01-01
    相关资源
    最近更新 更多