Project Unix Messages

/Concurrency/Messages: 

Purpose of the Assignment

  1. Get some more experience with fork and concurrently executing processes.
  2. Learn about messages and message queues in the Unix environment

There Was an Old Lady Who Swallowed a Fly

Refer to Wikipedia.

Preliminaries: Message Queues

You will need the following to process messages: 

You will need to include from sys ipc.h, msg.h, wait.h, and errno.h. 

You will have to declare a structure to hold the message that you are going to send. The first part of the message MUST be a long - mtype. After that, you can customize it to your needs. 

extern int errno;

#define MSGPERM 0600

int sendverseid;

struct sendverse

{ long mtype;

struct verse{

int childno;

char sheswealloweda[30];

char theverse[200];

}verse;

}qentry;

In order for processes to send/receive messages, a message queue is required. The system call required to obtain a message queue;

Prototype: int msgget (key_t key, int msgflag);

msgqid = msgget(IPC_PRIVATE,MSGPERM|IPC_CREAT|IPC_EXCL) 

Like semaphores and shared memory, message queues are permanent. They must be returned to the system. The system has a finite (not large) number of message queues. When a message queue is assigned to a user, that queue is assigned to that user until the user explicitly returns it to the system. If you obtain a message queue and your program terminates without returning it, the message queue is still assigned to you. If you log off, the message queue is still assigned to you. If enough users do this enough times, eventually the system will run out of message queues. Use ipcs and ipcrm to clean up or cs326clean.

The system call required to return a message queue:

rc = msgctl(msgqid,IPC_RMID,NULL);

We will only be accessing the message queues in wait mode. If a process attempts to receive a message from a message queue queue and there is no message queued, the process will be suspended until a message is placed on the queue by another process. If a process attempts to send a message in wait mode and there is no room on the message queue, the process will be suspended. We will always send messages in wait mode.

Important note:Once the message is placed in the queue by the send operation, the sending process continues execution. The sending process is only blocked if the message queue is full. Send and Receive are asynchronous.

Prototypes for sending/receiving:

int msgsnd (int msqid, struct *msgp, int msgsiz, int msgflg);

int msgrcv (int msqid, struct *msgp, int msgsiz, long msgtyp, int msgflg);

The actual system calls:

To send a message in wait mode:
struct sendverse recite;
rc = msgsnd(msgqid,&recite,sizeof(qentry.verse),0);

A positive (nonzero) value must be placed in recite.mtype This can be used to indicate a message type. In this project, we will not be using a message type, so any nonzero value may be used.

Pay attention to the size of the message; be sure to get it correct.

To receive a message in wait mode:
struct sendverse torecite;

rc = msgrcv(msgqid,&torecite,sizeof(qentry.verse),0,0);

Pay attention to the size of the message; be sure to get it correct.

If msgrcv is called with the flag set to IPC_NOWAIT and there is a message in the queue, it is returned in qentry. If msgrcv is called with the flag set to IPC_NOWAIT and there is no message in the queue, -1 is returned and errno is set to ENOMSG.

The msgtyp parameter in the msgrcv can be used to receive messages out of order. 

The message fields will be set as filled in by the sender. 

The sender must set a positive (nonzero) value must be in recite.mtype (see above) This could be used to indicate a message type, but it is not used in this project. can

Preliminaries: Unix Processes

The parent and the child are separate processes. The fork launches the child and the parent and child run independently and concurrently. The child is an exact copy of the parent. The child has a copy of all of the variables at the time of the fork. Therefore, at the time of the fork, the child "knows" everything the parent "knows", but then they are on their separate ways. Changes made to variables in the parent are in the parent only and unknown to the child and visa versa. We learned about processes/fork in previous assignments.

More on fork.

Suggestion on how to get started

Although you do not have to submit this, you are strongly encouraged to do the following before starting the deliverable:

  1. Write a program that obtains a message queue. Print out the message queue id. Your program should then execute fork to create a child process. The parent should print a message that it is about to send a message to the message queue. The parent should send a message to the message queue that contains the string "hi there". After sending the message, the parent should wait for the child to terminate and return the message queue. The child process should receive a message from the message queue and then print out the message it received and terminate.

To Do

To get started:

Download a skeleton file that compiles oldlady.c. It has constant strings declared for the verses to the rhyme that is to be cooperatively displayed.

The program

Your program is going to consist of a total of 10 processes:

The Parent

The parent should obtain the message queue. All 9 children will know the message queueid after they are created.

The parent should fork one child. This first child will be considered child 0. It will be the process that receives 8 messages, one from each of the other children. See below.

The parent should then fork 8 more children, children number 1-8. After each fork, the child of the fork should call the child function passing the child number.

The parent should then wait for all 9 children to terminate. After all 9 children have terminated, the parent must return the message queue.

Children 1-8

Each child is passed its child number. The number is associated with an entry in the character array swallowed for what was swallowed and an entry in thewords for the verse for that child.

The child should print a message stating it has control and its child number. The child should call getpid to get its pid and print it out. The child should then build a message with its child number, what was swallowed, and the verse. The message should then be sent on the message queue. The child should then terminate.

Child 0

Child 0 should print a message stating it has control. It should execute getpid to get its pid and print it out.

Child 0 should declare two, two-dimensional character arrays:

  1. The verses received
  2. What was swallowed associated with the verse

Child 0 will have two loops that execute 8 times, one for each verse.

First loop. Child 0 should receive a message, print out the child number it received the message from, and copy the verse into the appropriate entry in the versus character array and what was swallowed in the swallowed array.

Upon termination of the first loop, the rhyme should be assembled

Second loop. This is a nested loop. The outer loop will execute 8 times, one for each verse. Assuming it is a for loop with i=0; i<8;i++, at the top of the loop it should print "There was an old lady who swallowed a " with what was passed as swallowed for this loop iteration. It then should print the verse associated with this iteration. The inner loop should now execute from j=i-1;j>=0;j-- printing the remainder of the verse.

Child 0 should then terminate.

Print Buffering

Remember, the operating system buffers output for each process. In order to see the interleaving of processes, you must fflush(stdout) after each printf.

Remember

Message queues, shared memory, and semaphores are assigned to a process permanently. They must be returned. When your program crashes, be sure to clean up after yourself using IPCS and IPCRM or use cs326clean. If you do not do this, you will eventually use them all up and no one will be able to get any. You will become very unpopular.

Submit

  1. Use turnin to electronically  times to submit your program. Select oldlady The program name must be oldlady.c. .

Grade

Maintained by Barbara Bracken
Last Modified 3:34 PM 11/10/2024
This page is copyright protected © by Barbara Bracken