Reputation: 643
I'm trying to use fork() to implement a message queue. Here's what I've got.
#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;
}
I added my actual problem. Hopefully this isn't too much. This is a homework assignment but I didn't want to just get help with the code. Once again, the only result that I am getting is MESSAGE REC
rather than MESSAGE SENT
followed by MESSAGE REC
EDIT:
Okay, I added an error check for msq_pid == -1
. I also noticed that when I restarted my Virtual Machine, I was able to get both MESSAGE SENT
and MESSAGE REC
. After several more runs of the program, I then began only receiving MESSAGE REC
. Can someone explain this?
Upvotes: 0
Views: 130
Reputation: 16540
several of the system calls are being used incorrectly.
The returned status from several of the system calls are being ignored
The following code:
now, the code:
#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
Upvotes: 0
Reputation: 545
Per the fork() man page it seems your problem is that you have the child and parent inverted. fork() returns 0 to the child process, it returns > 0 to the parent, and returns -1 on error. So in your code you should have:
if(msg_pqid == 0) {
/* The child sends the message */
} else {
/* Parent receives the message */
}
I prefer to use a switch like so:
switch ((msg_pqid = fork())) {
case -1:
/* Error */
case 0:
/* Child sends message */
default:
/* Parent receives message */
}
Upvotes: 2