我创建了这个程序,将消息传递给父进程。我希望父进程打印出它收到的消息。我不确定这是否是读取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);
}
我的问题是,为什么在编译和执行此代码时,不会显示用于发送的消息?
答案 0 :(得分:2)
您还没有真正提出过问题,但我可以通过代码看到的几个问题是:
char *mymsg[1028];
...
mymsg[1] = "serving for sender\n";
这里有mymsg
,它是1028
指向char
的数组,用于表示字符串。 (顺便说一下,为什么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]);
或
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]);
编辑:在第二种情况下,你已经将字符串放在某处(而不是“这是一个字符串”),分配指针就足够了,你不需要复制或分配内存。但是,如果您的情况比这更复杂,并且在分配mymsg[1] = ...
和msgsnd
之间还有其他代码,则必须确保原始字符串保持活动状态,直到msgsnd
完成。否则,你有一个悬垂的指针,会导致你的问题。这是个主意:
+-+-+-+-+-+-+-+-+--+
str_to_be_printed ----->|A| |s|t|r|i|n|g|\0|
+-+-+-+-+-+-+-+-+--+
^
mymsg[1]---------------/
如果你free
str_to_be_printed
的内存,访问mymsg[1]
会导致分段错误/访问冲突。
请注意,我写的代码只是为了给你一个指导,不要复制粘贴它。
答案 1 :(得分:1)
与您的代码相关的观察很少。
errno
,即可用于检查错误的错误号。您可以使用perror
或strerror
查看消息(已由Jonathan Leffler指出)char *
发送msgsnd
&在struct msg
中收到msgrcv
类型。msgsz
但尚未初始化的电话。将msgsz
的值设置为您要发送/接收的大小。虽然发送给你似乎发送了17个字节但接收它时没有设置。mtype
的值应大于0
。pid
的类型应为pid_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;
}
您似乎在此处使用System V消息队列API,您可以查看POSIX消息队列API,如mq_open
,mq_close
,mq_send
,mq_receive
等。
有关消息队列概述,请参见手册页(man mq_overview
)
也可以使用手册页获取有关API的信息
希望这有帮助!
答案 2 :(得分:1)
你有几个问题:
您需要在致电fork()
之前创建消息队列,以便父母和子女都可以访问它;
消息队列的权限是根据msgget()
的第二个参数的低位设置的,因此您需要至少为消息队列的所有者指定读写权限。您可以在S_IRWXU
使用常量<sys/stat.h>
;
您正在向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);