CS644 POSIX Semaphores Example

 

/* A program derived from Robbins and Robbins ch12, ch14, and ch15 examples */

/* See http://vip.cs.utsa.edu/usp/programs.html and R&R book */

/* Shows use of POSIX semaphores to provide mutex between child processes */

#include <semaphore.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/shm.h>

#include <sys/stat.h>

 

/* Without use of shared memory, the semaphore doesn't work across

   processes!  Of course it would work with threads in one process,

   since they share the process address space. */

/* uncomment the next line to start using shared memory for sem_t object */

/*#define USE_SHARED_MEMORY */

 

#define MAXPIDS 10

void worker(int i, void * args);

 

int main(int argc, char *argv[]) {

   int error;

   int i;

   int id, n;

   sem_t *semlock;

   pid_t pids[MAXPIDS];

 

   if (argc != 2){   /* check for valid number of command-line arguments */

      fprintf (stderr, "Usage: %s numprocesses\n", argv[0]);

      return 1;

   }

   n = atoi(argv[1]);

   if (n > MAXPIDS)

       return 1;

 

#ifdef USE_SHARED_MEMORY

   if ((id = shmget(IPC_PRIVATE, sizeof(sem_t), (S_IRUSR|S_IWUSR))) == -1) {

       perror("Failed to create shared memory segment");

       return 1;

   }

   if ((semlock = (sem_t *)shmat(id, NULL, 0)) == (void *)-1) {

       perror("Failed to attach memory segment");

       return 1;

   }

#else

   /* try using ordinary process-private memory for sem_t variable */

   semlock = (sem_t *)malloc(sizeof(sem_t));

#endif

   if (sem_init(semlock, 1/*shared across processes*/, 1) == -1) {

      perror("Failed to initialize semaphore");

   } else {

       for (i = 0; i < n; i++) {

           if ((pids[i] = fork()) < 0) {

               fprintf(stderr, "Failed to create process:%s\n",

                       strerror(error));

               return 1;

           }

           if (pids[i] == 0) {          /* child */

               worker(i, semlock);

               exit(0);

           }

       }

       /* here in parent of all */

       for (i = 0; i < n; i++)

           wait(0);

       fprintf(stderr, "workers all done\n");

   }

#ifdef USE_SHARED_MEMORY

   if (shmdt((void *)semlock) == -1) {  /* shared memory detach */

       perror("Failed to destroy shared memory segment");

       return 1;

   }

#else

   free(semlock);

#endif

   return 0;

}

sf06.cs.umb.edu$ more semexworker.c

#include <errno.h>

#include <semaphore.h>

#include <stdio.h>

#include <unistd.h>

#define TEN_MILLION 10000000L

#define BUFSIZE 1024

 

void worker(int i, void * args)

{

   char buffer[BUFSIZE];

   char *c;

   sem_t *semlockp;

   struct timespec sleeptime;

 

   semlockp = (sem_t *)args;

   sleeptime.tv_sec = 0;

   sleeptime.tv_nsec = TEN_MILLION;

   snprintf(buffer, BUFSIZE, "This is process %ld\n",

           (long)getpid());

   c = buffer;

   setbuf(stderr, NULL);  // specify no buffering for stderr

   /****************** entry section *******************************/

   while (sem_wait(semlockp) == -1)        /* Entry section */

      if(errno != EINTR) {

         fprintf(stderr, "Thread failed to lock semaphore\n");

         return;

      }

   /****************** start of critical section *******************/

   while (*c != '\0') {

      fputc(*c, stderr); // no buffering: output each synchronously

      c++;

      nanosleep(&sleeptime, NULL);

   }

   /****************** exit section ********************************/

   if (sem_post(semlockp) == -1)         /* Exit section */

      fprintf(stderr, "Thread failed to unlock semaphore\n");

   /****************** remainder section ***************************/

   return;

}

 

 

 

 

 

 

Compile and load with realtime library –lrt:

 

sf06.cs.umb.edu$ gcc semex.c semexworker.c -lrt

sf06.cs.umb.edu$ a.out

 

 

Run without shared memory: no process coordination

 

Usage: a.out numprocesses

sf06.cs.umb.edu$ a.out 4

sf06.cs.umb.edu$ a.out 4

TTTThhhhiiiissss    iiiissss    pppprrrroooocccceeeessssssss    6666333388897890

 

 

 

workers all done

 

After editing in #define SHARED_MEMORY to use shared memory: mutex effect, processes run one at a time in the critical section

 

sf06.cs.umb.edu$ a.out 4

This is process 28368

This is process 28369

This is process 28370

This is process 28371

workers all done

sf06.cs.umb.edu$