Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Write your own simple client/server set of processes in the C language. There sh

ID: 3845959 • Letter: W

Question

Write your own simple client/server set of processes in the C language. There should be two files: client.c and server.c.

The client should use a shared memory segment to send a command message to the server.  

You may not use sockets or multithreading, as we have not gone over that yet in my class. We are supposed to be using semaphores and shared memory segments.

The server process should monitor the shared memory segment, and respond as follows:

"HI" -- The server prints "Greetings" to the screen.
"PID" -- The server prints it's process id to the screen.
"QUIT" -- The server terminates gracefully, detaching and releasing the shared memory segment.

**Note, please do not copy and paste a solution from here or Google. I am looking for a unique solution to help me better understand this assignment. Thank you.**

Hints :

Use polling (an intentional infinite loop) in the server to monitor the shared memory segment.

You will need some way to coordinate sharing the memory segment.

read man pages for shmdt, shmget, shmat, shmctl, semctl, semop, semget

I will now attach the code that I have so far, I am getting an error with the client.c saying "semget: File exists". I have tried changing the keys for semget but that doesn't seem to work. I don't know why it is saying I already have semaphores for those keys. The server runs fine, so far. Not sure if its done though.

Here is my server code so far:

#include "stdio.h"
#include "stdlib.h"
#include "sys/shm.h"
#include "sys/ipc.h"
#include "time.h"
#include "sys/types.h"
#include "sys/sem.h"
#include "signal.h"
#include "string.h"
#include <unistd.h>

#define MEM_KEY 90                       // like a filename
#define SEM_KEY 9900
#define SEG_SIZE ( (size_t)100 )           // size of segment
#define oops( m, x ) { perror(m); exit(x); }
int seg_id, semset_id;
union semun{ int val; struct semid_ds* buf; ushort* array; };
void wait_and_lock( int );
void release_lock( int );

int main()
{
char c;
char *memPtr;


if ((seg_id = shmget(MEM_KEY, SEG_SIZE, IPC_CREAT | 0777)) < 0)
oops("shmget", 1);

if ((memPtr = shmat(seg_id, NULL, 0)) == (char *) -1)
oops("shmat", 2);
  
semset_id = semget( SEM_KEY, 2, 0666 );

wait_and_lock( semset_id );

while(1)
{
printf("enter: ");
scanf("%s", memPtr);
}

release_lock( semset_id );
  
while (*memPtr != '*')
sleep(1);
  
shmdt( memPtr );  

exit(0);
}

void wait_and_lock( int semset_id )
{
   union semun sem_info;                   // some properties
   struct sembuf actions[2];               // action set, an array
  
   actions[0].sem_num = 1;                   // sem[1] is n_writers
   actions[0].sem_flg = SEM_UNDO;           // auto cleanup
   actions[0].sem_op = 0;                   // wait for 0
   actions[1].sem_num = 0;                   // sem[0] is n_readers
   actions[1].sem_flg = SEM_UNDO;           // auto cleanup
   actions[1].sem_op = 1;                   // incr n_readers
  
   if ( semop( semset_id, actions, 2 ) == -1 )
       oops( "semop: locking", 10 );
}

void release_lock( int semset_id )
{
   union semun sem_info;                   // some properties
   struct sembuf actions[1];               // action set
  
   actions[0].sem_num = 0;                   // sem[0] is n_readers
   actions[0].sem_flg = SEM_UNDO;           // auto cleanup
   actions[0].sem_op = -1;                   // decr reader country
  
   if ( semop( semset_id, actions, 1 ) == -1 )
       oops( "semop: unlocking", 10 );
}

and here is my client code so far:

#include "stdio.h"
#include "stdlib.h"
#include "sys/shm.h"
#include "sys/ipc.h"
#include "time.h"
#include "sys/types.h"
#include "sys/sem.h"
#include "signal.h"
#include "string.h"
#include <unistd.h>

#define MEM_KEY 90                       // like a filename
#define SEM_KEY 9900
#define SEG_SIZE ( (size_t)100 )           // size of segment
#define oops( m, x ) { perror(m); exit(x); }

union semun { int val; struct semid_ds* buf; unsigned short* array; };
int seg_id, semset_id;
void cleanup( int );
void set_sem_value( int, int, int );
void wait_and_lock( int );
void release_lock( int );

int main()
{
  
int id = 0;
char *memPtr, *s;
signal( SIGINT, cleanup );
   seg_id = shmget( MEM_KEY, SEG_SIZE, 0777 );
   if( seg_id == -1 )
       oops( "shmget", 1 );

if ((memPtr = shmat(seg_id, NULL, 0)) == (char *) -1)
oops("shmat",2);
  
   semset_id = semget( SEM_KEY, 2, ( 0666 | IPC_CREAT | IPC_EXCL ) );
  
   if ( semset_id == -1 )
       oops( "semget", 3 );
  
set_sem_value( semset_id, 0, 0 );
set_sem_value( semset_id, 1, 0 );

//Now read what the server put in the memory.
//while(1){
//for (s = shm; *s != ''; s++)
//putchar(*s);
//}
   while(1)
   {
   wait_and_lock( semset_id );  
   printf( " shm_ts2 update memory " );
   if(strcmp(memPtr, "HI")==0)
{
printf("Greetings! ");
fflush(stdout);
memPtr[0] = '';

}
else if(strcmp(memPtr, "PID")==0)
{
id = (int)getpid();
printf("Server pid: %i ", id);
fflush(stdout);
memPtr[0] = '';
  
}
else if(strcmp(memPtr, "QUIT")==0){
shmctl(seg_id, IPC_RMID, NULL);
shmdt(memPtr);
printf("GOODBYE! ");
exit(0);
}
release_lock( semset_id );
printf( " shm_ts2 released lock " );
   }

//putchar(' ');
*memPtr = '*';
   cleanup(0);
return 0;

}

void cleanup( int n )
{
   shmctl( seg_id, IPC_RMID, NULL );
   semctl( semset_id, 0, IPC_RMID, NULL );  
}


void set_sem_value( int semset_id, int semnum, int val )
{
   union semun initval;
  
   initval.val = val;
  
   if ( semctl( semset_id, semnum, SETVAL, initval ) == -1 )
       oops( "semctl", 4 );
}


void wait_and_lock( int semset_id )
{
   struct sembuf actions[2];               // action set, an array
  
   actions[0].sem_num = 0;                   // sem[0] is n_readers
   actions[0].sem_flg = SEM_UNDO;           // auto cleanup
   actions[0].sem_op = 0;               // wait til no readers
   actions[1].sem_num = 1; // sem[1] is n_writers
   actions[1].sem_flg = SEM_UNDO;       // auto cleanup
   actions[1].sem_op = 1;                   // increment number of writers
  
   if ( semop( semset_id, actions, 2 ) == -1 )
       oops("semop: locking", 10 );
}

// Thing 4: build and execute a 1-element action set: decrement num_writers
void release_lock( int semset_id )
{
   struct sembuf actions[1];               // action set, an array
   actions[0].sem_num = 1;                   // sem[0] is n_writers
   actions[0].sem_flg = SEM_UNDO;           // auto cleanup
   actions[0].sem_op = -1;                   // decrement number of writer count
  
   if ( semop( semset_id, actions, 1 ) == -1 )
       oops( "semop: unlocking", 10 );
}

A 10-point sample run: Terminal 1: rig N$ cc cl.c ocl cat rig N HI PID QUIT trig N]$ Terminal 2 at rig ne]$ cc server.c Server crig ne]$ ./server Greetings! Server pid: 24700 GOODBYE

Explanation / Answer

server.c