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. Here is my attempt:
我创建了这个程序,将消息传递给父进程。我希望父进程打印出它收到的消息。我不确定这是否是读取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);
}
My question is, why is the message serving for sending not being displayed when this code is compiled and executed?
我的问题是,当编译和执行此代码时,为什么发送的消息不显示?
3 个解决方案
#1
2
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. (By the way, why 1028? Not that it matters, but just so you know 2^10 is 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.
在这里你有mymsg,这是一个1028指向char的数组,它被视为一个字符串。 (顺便说一句,为什么1028?不重要,但只知道你知道2 ^ 10是1024)。但是,此数组包含未初始化且指向随机位置的指针。重要的是,没有为您想要放入其中的可能消息分配空间。
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. Here are two ways to do it:
更重要的是,你不能使用=复制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]);
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. 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. Otherwise, you have a dangling pointer which will cause you problems. Here's the idea:
编辑:在第二种情况下,你已经将字符串放在某处(而不是以“这是一个字符串”的形式),分配指针就足够了,你不需要复制或分配内存。但是,如果您的情况比这更复杂,并且在分配mymsg [1] = ...和msgsnd之间还有其他代码,则必须确保原始字符串保持活动直到msgsnd完成。否则,你有一个悬垂的指针,会导致你的问题。这是个主意:
+-+-+-+-+-+-+-+-+--+
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.
如果释放str_to_be_printed的内存,访问mymsg [1]会导致分段错误/访问冲突。
Note that, the code I wrote is just to give you a guideline, don't copy-paste it.
请注意,我写的代码只是为了给你一个指导,不要复制粘贴它。
#2
1
There are few observation related to your code.
与您的代码相关的观察很少。
- 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
i.e. error number which can be used to check for error. You can useperror
orstrerror
to see the message (Pointed out by Jonathan Leffler already) - You need to create message queue before using it (Again pointed out by Jonathan Leffler already).
- You are sending
char *
inmsgsnd
& receivingstruct msg
type inmsgrcv
. - You have set the size to be passed in the message queue send & receive calls, for which you are using
msgsz
but uninitialized. Set value ofmsgsz
to the size you want to send/receive. While sending you seem to sending 17 bytes but while receiving it is not set. -
mtype
should have a value greater than0
. - Type for
pid
should bepid_t
, which seems do you little good in this case anyway.
当您使用系统调用(任何返回任何错误代码的函数)时,请检查函数的返回值。在系统调用的情况下,您已经使用过将设置errno,即可用于检查错误的错误号。您可以使用perror或strerror来查看消息(Jonathan Leffler已经指出)
您需要在使用之前创建消息队列(Jonathan Leffler已经再次指出)。
您正在msgsnd中发送char *并在msgrcv中接收struct msg类型。
您已设置要在消息队列发送和接收呼叫中传递的大小,您正在使用msgsz但未初始化。将msgsz的值设置为您要发送/接收的大小。虽然发送你似乎发送17个字节,但接收它时没有设置。
mtype的值应大于0。
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
)
Use man pages for information about APIs as well.
Hope this helps!
您似乎在这里使用System V消息队列API,您可以查看POSIX消息队列API,如mq_open,mq_close,mq_send,mq_receive等。有关消息队列概述,请参阅手册页(man mq_overview)使用手册页获取有关API的信息同样。希望这可以帮助!
#3
1
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. You can use the constantS_IRWXU
from<sys/stat.h>
here;消息队列的权限是从msgget()的第二个参数的低位开始设置的,因此您需要至少为消息队列的所有者指定读写权限。你可以在这里使用
中的常量S_IRWXU; -
You are passing
msgsnd()
a pointer to a string, but it actually wants a pointer to a message struct like yourstruct msg
.您正在传递msgsnd()一个指向字符串的指针,但它实际上需要一个指向消息结构的指针,就像您的struct msg一样。
-
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);
#1
2
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. (By the way, why 1028? Not that it matters, but just so you know 2^10 is 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.
在这里你有mymsg,这是一个1028指向char的数组,它被视为一个字符串。 (顺便说一句,为什么1028?不重要,但只知道你知道2 ^ 10是1024)。但是,此数组包含未初始化且指向随机位置的指针。重要的是,没有为您想要放入其中的可能消息分配空间。
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. Here are two ways to do it:
更重要的是,你不能使用=复制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]);
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. 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. Otherwise, you have a dangling pointer which will cause you problems. Here's the idea:
编辑:在第二种情况下,你已经将字符串放在某处(而不是以“这是一个字符串”的形式),分配指针就足够了,你不需要复制或分配内存。但是,如果您的情况比这更复杂,并且在分配mymsg [1] = ...和msgsnd之间还有其他代码,则必须确保原始字符串保持活动直到msgsnd完成。否则,你有一个悬垂的指针,会导致你的问题。这是个主意:
+-+-+-+-+-+-+-+-+--+
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.
如果释放str_to_be_printed的内存,访问mymsg [1]会导致分段错误/访问冲突。
Note that, the code I wrote is just to give you a guideline, don't copy-paste it.
请注意,我写的代码只是为了给你一个指导,不要复制粘贴它。
#2
1
There are few observation related to your code.
与您的代码相关的观察很少。
- 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
i.e. error number which can be used to check for error. You can useperror
orstrerror
to see the message (Pointed out by Jonathan Leffler already) - You need to create message queue before using it (Again pointed out by Jonathan Leffler already).
- You are sending
char *
inmsgsnd
& receivingstruct msg
type inmsgrcv
. - You have set the size to be passed in the message queue send & receive calls, for which you are using
msgsz
but uninitialized. Set value ofmsgsz
to the size you want to send/receive. While sending you seem to sending 17 bytes but while receiving it is not set. -
mtype
should have a value greater than0
. - Type for
pid
should bepid_t
, which seems do you little good in this case anyway.
当您使用系统调用(任何返回任何错误代码的函数)时,请检查函数的返回值。在系统调用的情况下,您已经使用过将设置errno,即可用于检查错误的错误号。您可以使用perror或strerror来查看消息(Jonathan Leffler已经指出)
您需要在使用之前创建消息队列(Jonathan Leffler已经再次指出)。
您正在msgsnd中发送char *并在msgrcv中接收struct msg类型。
您已设置要在消息队列发送和接收呼叫中传递的大小,您正在使用msgsz但未初始化。将msgsz的值设置为您要发送/接收的大小。虽然发送你似乎发送17个字节,但接收它时没有设置。
mtype的值应大于0。
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
)
Use man pages for information about APIs as well.
Hope this helps!
您似乎在这里使用System V消息队列API,您可以查看POSIX消息队列API,如mq_open,mq_close,mq_send,mq_receive等。有关消息队列概述,请参阅手册页(man mq_overview)使用手册页获取有关API的信息同样。希望这可以帮助!
#3
1
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. You can use the constantS_IRWXU
from<sys/stat.h>
here;消息队列的权限是从msgget()的第二个参数的低位开始设置的,因此您需要至少为消息队列的所有者指定读写权限。你可以在这里使用
中的常量S_IRWXU; -
You are passing
msgsnd()
a pointer to a string, but it actually wants a pointer to a message struct like yourstruct msg
.您正在传递msgsnd()一个指向字符串的指针,但它实际上需要一个指向消息结构的指针,就像您的struct msg一样。
-
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);