Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的消息传递/从C中的结构打印字符数组_C_Struct_Message_Msgrcv - Fatal编程技术网

C中的消息传递/从C中的结构打印字符数组

C中的消息传递/从C中的结构打印字符数组,c,struct,message,msgrcv,C,Struct,Message,Msgrcv,我创建这个程序是为了向父进程传递消息。我希望父进程打印出它收到的消息。我不确定这是否与读取字符数组或消息传递有关,因为我对c语言编程非常陌生。以下是我的尝试: struct msg { long int mtype; /* message type */ char mtext[1028]; /* message text */ } msg; int pid, len; int msgflg = 0; int msqid; char

我创建这个程序是为了向父进程传递消息。我希望父进程打印出它收到的消息。我不确定这是否与读取字符数组或消息传递有关,因为我对c语言编程非常陌生。以下是我的尝试:

struct msg {
        long int    mtype;      /* message type */
        char        mtext[1028];   /* message text */
} msg;
int pid, len;
int msgflg = 0;
int msqid;
char *mymsg[1028];
size_t msgsz;
long int msgtyp;

switch(pid=fork()) //fork child process
{//Child process
case 0:
    mymsg[1] = "serving for sender\n";
    len = strlen(mymsg[1]);
    msgsnd(msqid,mymsg[1],len,msgflg);
    break;
case -1:
    printf("fork failed");
    exit(-1);
    break;
default:
    msg.mtype = 0;
    msqid = msgget(IPC_PRIVATE,msgflg); 
    wait((int *) 0);
    msgrcv(msqid,&msg,msgsz,msgtyp,IPC_NOWAIT);

    printf("%s",msg.mtext);
    msgctl(msqid, IPC_RMID, NULL);
    exit(0);
}

我的问题是,为什么在编译和执行此代码时没有显示用于发送的消息?

您还没有真正提出问题,但我可以看到代码中的几个问题是:

char *mymsg[1028];
...
mymsg[1] = "serving for sender\n";
这里有一个
mymsg
,它是指向
char
1028
指针的数组,可以将其视为字符串。(顺便问一下,为什么是1028?这并不重要,只是让你知道2^10是1024)。但是,此数组包含未初始化且指向随机位置的指针。重要的是,没有为可能要放入其中的消息分配空间

第二个问题是C中的数组以索引0开头,所以您可能想编写

mymsg[0] = "serving for sender\n";
然而,这并不重要

更重要的是,不能使用
=
复制C中的字符串,应该使用
strcpy
并复制到已分配的内存位置。以下是两种方法:

char mymsg[1028][1028];    // if you are sure your messages fit in 1028 chars
...
mymsg[1] = malloc(strlen("serving for sender)*sizeof(char)); // sizeof(char) not really needed
strcpy(mymsg[1], "serving for sender\n");
msgsnd(msqid,mymsg[1],len,msgflg);
free(mymsg[1]);

编辑:在第二种情况下,您已经在某个地方有了字符串(而不是以“thisastring”的形式),分配指针就足够了,您不需要复制或分配内存。但是,如果您的情况比这更复杂,并且在分配
mymsg[1]=…
msgsnd
之间还有其他代码,则必须确保原始字符串保持活动状态,直到
msgsnd
完成。否则,您将有一个悬空的指针,这将给您带来问题。我的想法是:

                        +-+-+-+-+-+-+-+-+--+
str_to_be_printed ----->|A| |s|t|r|i|n|g|\0|
                        +-+-+-+-+-+-+-+-+--+
                        ^
mymsg[1]---------------/
如果
释放
要打印的
str\u的内存
,访问
mymsg[1]
将导致分段错误/访问冲突


请注意,我编写的代码只是给您一个指导原则,不要复制粘贴它。

与您的代码相关的观察很少

  • 使用系统调用(返回任何错误代码的任何函数)时,请检查函数的返回值。对于您使用的系统调用,将设置
    errno
    ,即可用于检查错误的错误号。您可以使用
    perror
    strerror
    查看消息(Jonathan Leffler已经指出)
  • 您需要在使用消息队列之前创建它(Jonathan Leffler已经指出)
  • 您正在
    msgsnd
    中发送
    char*
    ,并在
    msgrcv
    中键入
    struct msg
  • 您已经设置了要在消息队列发送和接收呼叫中传递的大小,您正在使用
    msgsz
    ,但尚未初始化。将
    msgsz
    的值设置为要发送/接收的大小。发送时,您似乎在发送17个字节,但在接收时,未设置该字节
  • mtype
    的值应大于
    0
  • pid
    的类型应该是
    pid\u t
    ,这在这种情况下似乎没有什么好处 一些代码部分供您参考:

    #include <stdio.h> /*For perror*/
    ...
    /* Create message queue */
    msqid = msgget(IPC_PRIVATE, IPC_CREAT);
    if( 0 > msqid )
    {
     perror("msgget");
     /* Handle error as per your requirement */
    }
    
    ... 
    /* Sending & receiving messages */
    ...
    struct msg {
            long int    mtype;      /* message type */
            char        mtext[1028];   /* message text */
    } sender_msg, receiver_msg;
    ...
    
    size_t msgsz = 10; /* Send & receive 10 bytes, this can vary as per need. You can receive less than what was sent */
    ...
    switch(fork())
    {
    
    case 0: /* Child */
        sender_msg.mtype = 1;
        strncpy(sender_msg.mtext,"01234567890123", 1027);
        /* Sending the whole text size */
        if ( 0 > msgsnd(msqid, &sender_msg, strlen(sender_msg.mtext),msgflg))
        {
          perror("msgsnd");
          /* Handle error as per your requirement */
        }
    break;
    
    case -1:
        perror("fork");
        exit(-1);
    break;
    default:
        wait((int *) 0);
        receiver_msg.mtype = 1;
        /* Receive only 10 bytes as set in msgsz */
        if( 0 > msgrcv(msqid,&receiver_msg,msgsz,msgtyp,IPC_NOWAIT))
        {
          perror("msgrcv");
          /* Error handling */
        }
        printf("%s",receiver_msg.mtext);
        if (0 > msgctl(msqid, IPC_RMID, NULL))
        {
          perror("msgctl");
          /* Handle error as per your requirement */
        }
    break;
    
    }
    
    #包括/*用于perror*/
    ...
    /*创建消息队列*/
    msqid=msgget(IPC_PRIVATE,IPC_CREAT);
    如果(0>msqid)
    {
    佩罗尔(“msgget”);
    /*根据您的要求处理错误*/
    }
    ... 
    /*发送和接收消息*/
    ...
    结构味精{
    long int mtype;/*消息类型*/
    字符多行文字[1028];/*消息文字*/
    }发送方消息,接收方消息;
    ...
    大小\u t msgsz=10;/*发送和接收10个字节,可根据需要更改。您可以收到少于已发送的内容*/
    ...
    开关(fork())
    {
    案例0:/*儿童*/
    发送方\ u msg.mtype=1;
    strncpy(发送方消息多行文字,“01234567890123”,1027);
    /*发送整个文本大小*/
    如果(0>msgsnd(msqid和sender_msg,strlen(sender_msg.mtext),msgflg))
    {
    perror(“msgsnd”);
    /*根据您的要求处理错误*/
    }
    打破
    案例1:
    佩罗尔(“福克”);
    出口(-1);
    打破
    违约:
    等待((int*)0);
    接收器\u msg.mtype=1;
    /*仅接收msgsz中设置的10个字节*/
    如果(0>msgrcv(msqid和接收器消息、msgsz、msgtyp、IPC\U NOWAIT))
    {
    perror(“msgrcv”);
    /*错误处理*/
    }
    printf(“%s”,接收方消息.mtext);
    如果(0>msgctl(msqid,IPC_RMID,NULL))
    {
    perror(“msgctl”);
    /*根据您的要求处理错误*/
    }
    打破
    }
    
    您似乎在这里使用SystemV消息队列API,您可以查看POSIX消息队列API,如
    mq\u open
    mq\u close
    mq\u send
    mq\u receive
    等。 有关消息队列概述,请参阅手册页(
    man mq_overview

    使用手册页也可以获取有关API的信息。

    希望这有帮助

    您有几个问题:

    • 您需要在调用
      fork()
      之前创建消息队列,以便父级和子级都可以访问它

    • 消息队列的权限是从
      msgget()
      的第二个参数的低位设置的,因此您至少需要为消息队列的所有者指定读写权限。您可以在这里使用
      中的常量
      S\u IRWXU

    • 您正在传递
      msgsnd()
      一个指向字符串的指针,但实际上它需要一个指向消息结构的指针,如
      struct msg

    • 您应该检查
      msgrcv()
      是否失败

    修复这些问题后,更正后的代码如下所示:

    int pid;
    int msqid;
    
    msqid = msgget(IPC_PRIVATE, S_IRWXU);
    
    if (msgid < 0) {
        perror("msgget");
        exit(1);
    }
    
    switch(pid=fork()) //fork child process
    {//Child process
    case 0:
        msg.mtype = 1;  /* Must be a positive value */
        strcpy(msg.mtext, "serving for sender\n");
        msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0);
        break;
    case -1:
        printf("fork failed");
        exit(2);
        break;
    default:
        wait(NULL);
    
        if (msgrcv(msqid, &msg, sizeof msg.mtext, 0, IPC_NOWAIT) >= 0)
            printf("%s",msg.mtext);
        else
            perror("msgrcv");
    
        msgctl(msqid, IPC_RMID, NULL);
        exit(0);
    
    intpid;
    int msqid;
    msqid=msgget(IPC_PRIVATE,S_IRWXU);
    如果(msgid<0){
    佩罗尔(“msgget”);
    出口(1);
    }
    开关(pid=fork())//fork子进程
    {//子进程
    案例0:
    msg.mtype=1;/*必须为正值*/
    strcpy(msg.mtext,“服务于
    
    int pid;
    int msqid;
    
    msqid = msgget(IPC_PRIVATE, S_IRWXU);
    
    if (msgid < 0) {
        perror("msgget");
        exit(1);
    }
    
    switch(pid=fork()) //fork child process
    {//Child process
    case 0:
        msg.mtype = 1;  /* Must be a positive value */
        strcpy(msg.mtext, "serving for sender\n");
        msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0);
        break;
    case -1:
        printf("fork failed");
        exit(2);
        break;
    default:
        wait(NULL);
    
        if (msgrcv(msqid, &msg, sizeof msg.mtext, 0, IPC_NOWAIT) >= 0)
            printf("%s",msg.mtext);
        else
            perror("msgrcv");
    
        msgctl(msqid, IPC_RMID, NULL);
        exit(0);