[英]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_printed
对mymsg[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. 与您的代码相关的观察很少。
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) perror
或strerror
查看消息(已经由Jonathan Leffler指出) char *
in msgsnd
& receiving struct msg
type in msgrcv
. msgsnd
中发送char *
并在msgrcv
接收struct msg
类型。 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. mtype
should have a value greater than 0
. mtype
的值应大于0
。 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_open
, mq_close
, mq_send
, mq_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.