$29.99
CECS 326-01 Assignment 4 (10 points)
Cooperating processes need to communicate between them. Linux supports shared memory for interprocess communication in two different implementations: POSIX and System V. A System V shared memory segment can be created and controlled using system calls shmget, shmctl, shmat, shmdt, and a C library function memcpy. Please consult the man pages of these system calls for details. This assignment is designed to illustrate a critical problem with processes executing concurrently that try to access shared data.
For this assignment you need to copy the following two C++ programs (named shmp2.cpp and shmc2.cpp) and a header file booking.h into your Linux directory, compile the two programs into shmp2, and shmc2, respectively. Then run shmp2 and observe what happens. Run shmp2 at least 5 times and observe, report the results and explain what may have caused the peculiarities in the outcome. Your observations and explanation should be reported on the cover page, along with the program description.
BE AWARE that blank lines in a Word document may have extra special characters that gnu compilers don’t recognize. Should you encounter errors due to this problem, delete each blank line and put it back while on the Linux text editor.
The program must run successfully on Linux.
Do the following for this assignment:
1. Compile shmp2.cpp and shmc2.cpp into shmp2 and shmc2, respectively, and run shmp2. Document what the programs are designed to do on the cover page.
2. Annotate the programs with adequate amount of comments throughout the program to explain what the program does. System calls require especially detailed comments and must be in your own words. Simply copying the text from the man pages are not acceptable.
3. Run shmp2 at least 5 times and observe the results. Explain the problems you have observed in these runs and explain what may be causing the peculiar outcomes on the cover page.
4. Submit on BeachBoard the annotated shmp2.cpp and shmc2.cpp, a screenshot that shows successful compile of the two programs as well as results of 5 runs, and a cover page that provides your name, your student ID, course # and section, assignment #, due date, submission date, a clear program description, and your observations & explanation of the run results. Format of the cover page should follow the cover page template on BeachBoard.
5. The programs must be properly formatted and adequately commented to enhance readability and understanding.
/* booking.h */
/* Header file to be used with
* shmp2.cpp and shmc2.cpp
*/
struct BUS {
char bus_number[6];
char date[9];
char title[50];
int seats_left;
};
/* shmp2.cpp */
#include "booking.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
BUS mybus = { "4321", "11262021", "Grand Canyon Tour", 20 };
#define NCHILD 3
int shm_init( void * );
void wait_and_wrap_up( int [], void *, int );
void rpterror( char *, char * );
int main(int argc, char *argv[])
{
int child[NCHILD], i, shmid;
void *shm_ptr;
char ascshmid[10], pname[14];
shmid = shm_init(shm_ptr);
sprintf (ascshmid, "%d", shmid);
cout << "Bus " << mybus.bus_number << " for "
<< mybus.title << " on " << mybus.date << ", "
<< mybus.seats_left << " seats available. " << endl;
cout << "Booking begins: " << endl << endl;
for (i = 0; i < NCHILD; i++) {
child[i] = fork();
switch (child[i]) {
case -1:
sprintf (pname, "child%d", i+1);
rpterror ((char *)"fork failed", pname);
exit(1);
case 0:
sprintf (pname, "shmc%d", i+1);
execl("shmc2", pname, ascshmid, (char *)0);
rpterror ((char *)"execl failed", pname);
exit (2);
}
}
wait_and_wrap_up (child, shm_ptr, shmid);
}
int shm_init(void *shm_ptr)
{
int shmid;
shmid = shmget(ftok(".",'u'), sizeof(BUS), 0600 | IPC_CREAT);
if (shmid == -1) {
perror ("shmget failed");
exit(3);
}
shm_ptr = shmat(shmid, (void * ) 0, 0);
if (shm_ptr == (void *) -1) {
perror ("shmat failed");
exit(4);
}
memcpy (shm_ptr, (void *) &mybus, sizeof(BUS) );
return (shmid);
}
void wait_and_wrap_up(int child[], void *shm_ptr, int shmid)
{
int wait_rtn, w, ch_active = NCHILD;
while (ch_active > 0) {
wait_rtn = wait( (int *)0 );
for (w = 0; w < NCHILD; w++)
if (child[w] == wait_rtn) {
ch_active--;
break;
}
}
cout << "Parent removing shm" << endl;
shmdt (shm_ptr);
shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0);
exit (0);
}
void rpterror(char *string, char *pname)
{
char errline[50];
sprintf (errline, "%s %s", string, pname);
perror (errline);
}
/* shmc2.cpp */
#include "booking.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
BUS *bus_ptr;
void *memptr;
char *pname;
int shmid, ret;
void rpterror(char *), srand(), perror(), sleep();
void sell_seats();
int main(int argc, char* argv[])
{
if (argc < 2) {
fprintf (stderr, "Usage:, %s shmid\n", argv[0]);
exit(1);
}
pname = argv[0];
sscanf (argv[1], "%d", &shmid);
memptr = shmat (shmid, (void *)0, 0);
if (memptr == (char *)-1 ) {
rpterror ((char *)"shmat failed");
exit(2);
}
bus_ptr = (struct BUS *)memptr;
sell_seats();
ret = shmdt(memptr);
exit(0);
}
void sell_seats()
{
int all_out = 0;
srand ( (unsigned) getpid() );
while ( !all_out) { /* loop to sell all seats */
if (bus_ptr->seats_left > 0) {
sleep ( (unsigned)rand()%2 + 1);
bus_ptr->seats_left--;
sleep ( (unsigned)rand()%5 + 1);
cout << pname << " SOLD SEAT -- "
<< bus_ptr->seats_left << " left" << endl;
}
else {
all_out++;
cout << pname << " sees no seats left" << endl;
}
sleep ( (unsigned)rand()%5 + 1);
}
}
void rpterror(char* string)
{
char errline[50];
sprintf (errline, "%s %s", string, pname);
perror (errline);
}