简体   繁体   English

消息传入C /从C中的结构打印char数组

[英]Message Passing In C/Printing a char array from a struct in C

I created this program to pass a message to a parent process. 我创建了此程序以将消息传递给父进程。 I want the parent process to print out the message it receives. 我希望父进程打印出它收到的消息。 I'm not sure if this is an issue with reading the char array or message passing as I am quite new to programming in c. 我不确定这是读取char数组还是传递消息的问题,因为我对使用c语言编程很陌生。 Here is my attempt: 这是我的尝试:

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);
}

My question is, why is the message serving for sending not being displayed when this code is compiled and executed? 我的问题是,为什么在编译和执行此代码时不显示用于发送的消息?

You haven't really asked a question, but a couple of issues I can see with the code are: 您尚未真正问过一个问题,但是我在代码中看到的几个问题是:

char *mymsg[1028];
...
mymsg[1] = "serving for sender\n";

Here you have mymsg which is an array of 1028 pointers to char , which is intended to be treated as a string. 在这里,您有mymsg ,它是1028指向char指针的数组,该指针应被视为字符串。 (By the way, why 1028? Not that it matters, but just so you know 2^10 is 1024). (顺便说一句,为什么是1028?这没关系,但是您知道2 ^ 10是1024)。 However, this array contains pointers that are not initialized and are pointing to random locations. 但是,此数组包含未初始化并且指向随机位置的指针。 Important thing is, there is no space allocated for the possible message you want to put in them. 重要的是,没有为要放入的消息分配空间。

Second issue is that arrays in C start with index 0, so you probably meant to write 第二个问题是C中的数组以索引0开头,因此您可能想写

mymsg[0] = "serving for sender\n";

That doesn't matter however. 但这无关紧要。

More importantly, you can't copy strings in C using = , you should use strcpy and copy to a memory location that you have already allocated. 更重要的是,不能使用=复制C中的字符串,而应使用strcpy并将其复制到已经分配的内存位置。 Here are two ways to do it: 这有两种方法:

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]);

or 要么

char *mymsg[1028];
...
char str_to_be_printed[] = "serving for sender\n";
mymsg[1] = malloc(strlen(str_to_be_printed)*sizeof(char)); // sizeof(char) not really needed
strcpy(mymsg[1], str_to_be_printed);
msgsnd(msqid,mymsg[1],len,msgflg);
free(mymsg[1]);

Edit: In the second case where you already have the string somewhere (and not in the form of "this is a string"), assigning the pointers is enough and you don't to copy or allocate memory. 编辑:在第二种情况下,您已经在某个位置放置了字符串(而不是以“ this is a string”的形式),分配指针就足够了,并且您无需复制或分配内存。 However, if your situation is more complex than this, and between assignment of mymsg[1] = ... and msgsnd there are other code, you have to make sure the original string stays alive until msgsnd is done. 但是,如果您的情况比这更复杂,并且在分配mymsg[1] = ...msgsnd还有其他代码,则必须确保原始字符串保持活动状态,直到完成msgsnd Otherwise, you have a dangling pointer which will cause you problems. 否则,您将有一个悬空的指针,这将导致您遇到问题。 Here's the idea: 这是想法:

                        +-+-+-+-+-+-+-+-+--+
str_to_be_printed ----->|A| |s|t|r|i|n|g|\0|
                        +-+-+-+-+-+-+-+-+--+
                        ^
mymsg[1]---------------/

If you free the memory of str_to_be_printed , access to mymsg[1] would cause segmentation fault/access violation. 如果free str_to_be_printed的内存, str_to_be_printedmymsg[1]访问将导致分段错误/访问冲突。

Note that, the code I wrote is just to give you a guideline, don't copy-paste it. 请注意,我编写的代码只是为您提供指导,请勿复制粘贴。

There are few observation related to your code. 与您的代码相关的观察很少。

  1. When you use system calls (any function which returns any error code) check the return value of the function. 使用系统调用(任何返回错误代码的函数)时,请检查该函数的返回值。 In the case of system calls you have used will set errno ie error number which can be used to check for error. 在使用系统调用的情况下,将设置errno即错误号,可用于检查错误。 You can use perror or strerror to see the message (Pointed out by Jonathan Leffler already) 您可以使用perrorstrerror查看消息(已经由Jonathan Leffler指出)
  2. You need to create message queue before using it (Again pointed out by Jonathan Leffler already). 您需要先创建消息队列,然后再使用它(再次由Jonathan Leffler指出)。
  3. You are sending char * in msgsnd & receiving struct msg type in msgrcv . 您要在msgsnd中发送char *并在msgrcv接收struct msg类型。
  4. You have set the size to be passed in the message queue send & receive calls, for which you are using msgsz but uninitialized. 您已设置要在消息队列发送和接收呼叫中传递的大小,您正在使用msgsz但未初始化该大小。 Set value of msgsz to the size you want to send/receive. msgsz值设置为要发送/接收的大小。 While sending you seem to sending 17 bytes but while receiving it is not set. 在发送时,您似乎发送了17个字节,但在接收时未设置。
  5. mtype should have a value greater than 0 . mtype的值应大于0
  6. Type for pid should be pid_t , which seems do you little good in this case anyway. pid类型应该为pid_t ,在这种情况下,您看起来还是有点不好。

Some code sections for your reference: 一些代码节供您参考:

#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;

}

You seem to be using System V message queues APIs here, you can look into the POSIX message queue APIs like mq_open , mq_close , mq_send , mq_receive etc. For message queue overview see the man pages ( man mq_overview ) 您似乎在这里使用System V消息队列API,可以查看POSIX消息队列API,例如mq_openmq_closemq_sendmq_receive等。有关消息队列的概述,请参见手册页( man mq_overview
Use man pages for information about APIs as well. 也可以使用手册页获取有关API的信息。
Hope this helps! 希望这可以帮助!

You have several problems: 您有几个问题:

  • You need to create the message queue before you call fork() , so that both the parent and child have access to it; 您需要在调用fork()之前创建消息队列,以便父级和子级都可以访问它。

  • The permissions of the message queue are set from the low-order bits of the second parameter of msgget() , so you need to specify at least read and write permissions for the owner of the message queue. 消息队列的权限是从msgget()的第二个参数的低位设置的,因此您至少需要为消息队列的所有者指定读写权限。 You can use the constant S_IRWXU from <sys/stat.h> here; 您可以在此处使用<sys/stat.h>的常量S_IRWXU

  • You are passing msgsnd() a pointer to a string, but it actually wants a pointer to a message struct like your struct msg . 您正在传递msgsnd()指向字符串的指针,但实际上它想要一个指向消息结构(如struct msg msgsnd()的指针。

  • You should check for msgrcv() failing. 您应该检查msgrcv()失败。

With these issues fixed, the corrected code looks like: 解决了这些问题后,更正后的代码如下所示:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM