我正在尝试使用fork()来实现消息队列。这就是我所拥有的。
#define DATA_SIZE 256
#define BUFF_SIZE 4096
int main(void) {
// seed the random number generator
srand(time(NULL));
// Parent and Ground Truth Buffers
char ground_truth[BUFF_SIZE] = {0}; // used to verify
char producer_buffer[BUFF_SIZE] = {0}; // used by the parent
int i = 0;
int msqid = 0;
int rc;
pid_t msq_pid;
for (i = 0; i < BUFF_SIZE; ++i) {
producer_buffer[i] = ground_truth[i] = rand() % 256;
}
const key_t s_msq_key = 1337; // used to create message queue ipc
const char *const p_msq_key = "/OS_MSG";
msqid = msgget(s_msq_key, IPC_CREAT | 0660);
msq_pid = fork();
if(msq_pid == -1){
perror("error forking");
exit(1);
}
if(msq_pid > 0){
rc = msgsnd(msqid, (void*)p_msq_key, sizeof(producer_buffer), 0);
printf("MESSAGE SENT\n");
if(rc < 0){
perror("message send failed");
exit(1);
}
return 1;
} else {
if(memcmp(producer_buffer, ground_truth, DATA_SIZE) == 0){
printf("MESSAGE REC");
return 1;
}
exit(1);
}
return 0;
}
我添加了我的实际问题。希望这不是太多。这是家庭作业,但我不想只是获得代码的帮助。再一次,我得到的唯一结果是MESSAGE REC
而非MESSAGE SENT
后跟MESSAGE REC
编辑:
好的,我添加了msq_pid == -1
的错误检查。我还注意到,当我重新启动虚拟机时,我能够同时获得MESSAGE SENT
和MESSAGE REC
。在多次运行该程序后,我开始只接收MESSAGE REC
。有人可以解释一下吗?
答案 0 :(得分:2)
根据fork()手册页,您的问题似乎是您让孩子和父母倒置了。 fork()向子进程返回0,返回&gt; 0到父级,并在出错时返回-1。所以在你的代码中你应该有:
if(msg_pqid == 0) {
/* The child sends the message */
} else {
/* Parent receives the message */
}
我更喜欢使用这样的开关:
switch ((msg_pqid = fork())) {
case -1:
/* Error */
case 0:
/* Child sends message */
default:
/* Parent receives message */
}
答案 1 :(得分:0)
正在错误地使用了几个系统调用。
正在忽略来自多个系统调用的返回状态
以下代码:
现在,代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h> //time()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h> //fork()
#include <string.h> //memcmp()
#define MAX_MSG_LEN (10)
#define ACT_MSG_LEN (8)
// Parent and Ground Truth Buffers
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[ MAX_MSG_LEN ]; /* message data */
};
struct msgbuf ground_truth; // used to verify
struct msgbuf producer_buffer = {1,"message"}; // used by the parent
int main(void)
{
// seed the random number generator
srand((unsigned)time(NULL));
//int i = 0;
int msqid = 0;
int rc;
pid_t msq_pid;
ssize_t rcvStatus;
const key_t s_msq_key = 1337; // used to create message queue ipc
//const char *const p_msq_key = "/OS_MSG";
msqid = msgget(s_msq_key, IPC_CREAT | 0660);
if( -1 == msqid )
{// then msgget failed
perror( "msgget failed");
exit( EXIT_FAILURE );
}
// implied else, msgget successful
msq_pid = fork();
while(1)
{
switch( msq_pid )
{
case -1:
perror("error forking");
exit( EXIT_FAILURE );
break;
default: // parent process
rc = msgsnd(msqid, &producer_buffer, sizeof producer_buffer, 0);
printf("MESSAGE SENT: %s\n", producer_buffer.mtext);
if(rc < 0)
{
perror("message send failed");
exit( EXIT_FAILURE );
}
break;
case 0: // child process
rcvStatus = msgrcv( msqid, &ground_truth, sizeof( ground_truth ), 0, 0);
if( -1 == rcvStatus )
{ // then msgrcv failed
perror( "msgrcv failed" );
exit( EXIT_FAILURE );
}
// implied else, msgrcv successful
if(memcmp(producer_buffer.mtext, ground_truth.mtext, ACT_MSG_LEN) == 0)
{
printf("MESSAGE REC %s\n", ground_truth.mtext);
}
else
{
printf( "msg Sent: '%s' does not match msg Recv: '%s'\n", producer_buffer.mtext, ground_truth.mtext);
}
break;
} // end switch
} // end while forever
} // end function: main