Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

test_shm.c

This example shows how to use the function create_shared_memory_segment().

/* ====================================================================== */
/* Please remember that you should define the build target (could be      */
/* SUN or LINUX). This is required for the semaphore/SHM library.         */
/* This program works as a Productor/Consumer test. Example of use:       */
/*                                                                        */
/* $ ./shm.test 50 1024 create 6 &                                        */
/*   This command line create a "productor". This process will perform    */
/*   the following actions:                                               */
/*   (a) Create a shared memory segment.                                  */
/*   (b) Create a set of 3 semaphores.                                    */
/*   (c) Wait for a "consumer" to appear (this is done by taking a sema-  */
/*       -phore that will be incremented by the "consumer").              */
/*                                                                        */
/* $ ./shm.test 50 1024 get 6 &                                           */
/*   This command line will create a "consumer". This process will awake  */
/*   the (waiting) "productor". The "consumer" will perform the following */
/*   actions:                                                             */
/*   (a) Get and attach the shared memory segment.                        */
/*   (b) Get the set of semaphores.                                       */
/*                                                                        */
/* Then the "consumer" xill read - and print - data produced by the       */
/* "productor".                                                           */
/* ====================================================================== */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include "my_shm.h"
#include "my_sem.h"

#define NO_ACTION     -1
#define CREATE_SHM    0
#define GET_SHM       1



#define NUMBER_OF_SEM 3   /* number of semaphores */
#define ELEMENT       0   /* semaphore            */
#define SPACE         1   /* semaphore            */
#define START         2   /* semaphore            */




int main (int argc, char *argv[])
{
  int ipc_key, shm_size, action, cr, sem_number, sem_values[NUMBER_OF_SEM], data, max_data;

  /* ==================================================================== */
  /* Check the command line arguments                                     */
  /* ==================================================================== */

  if (argc != 5)
  {
     fprintf (stderr, "\nUsage: shm.test <IPC key (shm and sem)> <SHM size> <action> <max data>");
     fprintf (stderr, "\n       -- if 'IPC key' is equal to -1, then the system choose the IPC keys");
     fprintf (stderr, "\n       -- 'action' could be 'create' or 'get'");
     fprintf (stderr, "\n");
     return 1;
  }

  ipc_key    = atoi(argv[1]);
  shm_size   = atoi(argv[2]);
  sem_number = NUMBER_OF_SEM;
  max_data   = atoi(argv[4]);

  action = NO_ACTION;
  if (strcmp(argv[3], "create") == 0) { action = CREATE_SHM; }
  if (strcmp(argv[3], "get")    == 0) { action = GET_SHM;    }

  if (action == NO_ACTION)
  {
     fprintf (stderr, "\nInvalid action (must be 'create' or 'get')\n");
     return 1;
  }

  /* ==================================================================== */
  /* Create or get (if already created) the SHM                           */
  /* Create or get (if already created) the semaphores                    */
  /* ==================================================================== */

  switch (action)
  {
    case CREATE_SHM:
         {
            /* ========================================================== */
            /* Create the Shared Memory Segment                           */
            /* ========================================================== */

            fprintf (stdout, "\nProductor: Create Shared Memory Segment\n"); fflush (stdout);

            cr = create_shared_memory_segment ((key_t)ipc_key, shm_size);
            switch (cr)
            {
              case CREATE_SHM_ALREADY_CREATED:
                   fprintf (stderr, "\nCan not create SHM: already created\n");
                   return 1;

              case CREATE_SHM_ERROR:
                   fprintf (stderr, "\nCan not create SHM: system error - %s\n", strerror(errno));
                   return 1;
            }

            /* ========================================================== */
            /* Create the set of semaphores                               */
            /* ========================================================== */

            fprintf (stdout, "\nProductor: Create set of semaphores\n"); fflush (stdout);

            cr = create_semaphore_set ((key_t)ipc_key+1, sem_number);
            switch (cr)
            {
              case CREATE_SEMAPHORE_CREATE_ERROR:
                   fprintf (stderr, "\nCan not create SEM - %s\n", strerror(errno));
                   return 1;

              case CREATE_SEMAPHORE_SET_VAL_ERROR:
                   fprintf (stderr, "\nCan not set SEM values - %s\n", strerror(errno));
                   return 1;
            }
         }; break;

    case GET_SHM:
         {
            /* ========================================================== */
            /* Get the Shared Memory Segment                              */
            /* ========================================================== */

            fprintf (stdout, "\nConsumer: Get Shared Memory Segment\n"); fflush (stdout);

            cr = get_shared_memory_segment_sys_id ((key_t)ipc_key, shm_size);
            switch (cr)
            {
              case GET_SHM_ALREADY_GET:
                   fprintf (stderr, "\nCan not get SHM's id: already get\n");
                   return 1;

              case GET_SHM_ERROR:
                   fprintf (stderr, "\nCan not get SHM's id: system error - %s\n", strerror(errno));
                   return 1;
            }

            /* ========================================================== */
            /* Get the set of semaphores                                  */
            /* ========================================================== */

            fprintf (stdout, "\nConsumer: Get set of semaphores\n"); fflush (stdout);

            cr = get_semaphore_set ((key_t)ipc_key+1, 2);
            switch (cr)
            {
              case GET_SEM_ALREADY_GET:
                   fprintf (stderr, "\nCan not get SEM - The process already got the semaphores\n");
                   return 1;

              case GET_SEM_ERROR:
                   fprintf (stderr, "\nError while getting set of semaphores - %d - %s\n", errno, strerror(errno));
                   return 1;
            }
         }; break;
  }

  /* ==================================================================== */
  /* Once created, the SHM must be attached to the process                */
  /* ==================================================================== */

  if (attache_shared_memory_segment() == (SHM_addr)-1)
  {
     fprintf (stderr, "\nError while attaching the SHM - %s\n", strerror(errno));
     return 1;
  }

  /* ==================================================================== */
  /* Print information                                                    */
  /* ==================================================================== */

  fprintf (stdout, "\n");
  fprintf (stdout, "\nProcess ID is:          %d",  (int)getpid());
  fprintf (stdout, "\nSHM system ID is:       %d",  get_shared_memory_segment_id());
  fprintf (stdout, "\nSHM bind address is:    %0X", (unsigned int)attache_shared_memory_segment());
  fprintf (stdout, "\nAttachemant number is:  %d",  (int)(get_shm_info()->shm_nattch));
  fprintf (stdout, "\n");

  /* ==================================================================== */
  /* Set all shared memory segment to zero                                */
  /* ==================================================================== */

  memset ((void*)get_shm_address(), 0, shm_size);

  /* ==================================================================== */
  /* Implement a basic productor / consumer protocol                      */
  /* ==================================================================== */

    /* ================================================================== */
    /* We need to synchronize the productor and the consumer ...          */
    /* ================================================================== */

    if (action == CREATE_SHM)
    {
      fprintf (stdout, "\nProductor: Set ELEMENT value to 0");
      fprintf (stdout, "\nProductor: Set SPACE value to 1");
      fprintf (stdout, "\nProductor: Set START value to 0 and take it => I should go to sleep");
      fflush (stdout);

      sem_values[ELEMENT] = 0;
      sem_values[SPACE]   = 1;
      sem_values[START]   = 0;

      cr = set_semaphore_values (sem_values);
      switch(cr)
      {
        case SET_SEM_VALUES_SEM_NOT_CREATED:
             fprintf (stderr, "\nProductor: Error while setting semaphores' values - Semaphores not created\n");
             return 1;
        case SET_SEM_VALUES_SET_ERROR:
             fprintf (stderr, "\nProductor: Error while setting semaphores' values - %s\n", strerror(errno));
             return 1;
      }

      if (take_sem(START) == -1)
      {
        fprintf (stderr, "\nProductor: Error while tacking START  - %s\n", strerror(errno));
        return 1;
      }

      fprintf (stdout, "\nProductor (%d): I have START!", (int)getpid());
      fflush (stdout);
    }

    /****/

    if (action == GET_SHM)
    {
      fprintf (stdout, "\nConsumer: Set START to 1, this should awake the productor ...\n");
      fflush (stdout);

      cr = set_semaphore_value (1, START);
      switch(cr)
      {
        case SET_SEM_VALUES_SEM_NOT_CREATED:
             fprintf (stderr, "\nConsumer: Error while setting START to 1 - Semaphores not get\n");
             return 1;
        case SET_SEM_VALUES_SET_ERROR:
             fprintf (stderr, "\nConsumer: Error while setting START to 1 - %s\n", strerror(errno));
             return 1;
      }
    }

    /* ================================================================== */
    /* OK, now the productor is running with the consumer                 */
    /* -> The productor gets ELEMENT.                                     */
    /* -> The consumer gets SPACE.                                        */
    /*                                                                    */
    /* The situation is clear ... lets proceed                            */
    /* ================================================================== */

    data = 0;

    while(data != -1)
    {
      /* ================================================================ */
      /*                            PRODUCTOR                             */
      /* ================================================================ */

      if (action == CREATE_SHM)
      {
        if (take_sem(SPACE) == -1)
        {
          fprintf (stderr, "\nProductor: Error while tacking PLACE - %s\n", strerror(errno));
          return 1;
        }

        if (data > max_data) { data = -1; }

        memcpy ((void*)get_shm_address(), (void*)&data, sizeof(int));
        sleep (1);

        if (release_sem(ELEMENT) == -1)
        {
          fprintf (stderr, "\nProductor: Error while releasing ELEMENT - %s\n", strerror(errno));
          return 1;
        }

        fprintf (stdout, "\nProductor: %d", data);
        fflush(stdout);


        if (data != -1) { data++; }
      }

      /* ================================================================ */
      /*                            CONSUMER                              */
      /* ================================================================ */

      if (action == GET_SHM)
      {
        if (take_sem(ELEMENT) == -1)
        {
          fprintf (stderr, "\nConsumer: Error while getting ELEMENT - %s\n", strerror(errno));
          return 1;
        }

        memcpy ((void*)&data, (void*)get_shm_address(), sizeof(int));

        if (release_sem(SPACE) == -1)
        {
          fprintf (stderr, "\nConsumer: Error while releasing PLACE - %s\n", strerror(errno));
          return 1;
        }

        fprintf (stdout, "\nConsumer: %d", data);
        fflush(stdout);
      }
    }

  /* ==================================================================== */
  /* return                                                               */
  /* ==================================================================== */

  if (action == CREATE_SHM)
  {
    fprintf (stdout, "\nProductor: exit now\n\n");

    if (set_shm_auto_destroy() == -1)
    {
      fprintf (stderr, "\nProductor: Error while setting SHM into auto-destry mode - %s\n", strerror(errno));
      return 1;
    }

    if (detache_shm() == -1)
    {
      fprintf (stderr, "\nProductor: Error while detaching SHM  - %s\n", strerror(errno));
      return 1;
    }

    if (release_sem(START) == -1)
    {
      fprintf (stderr, "\nProductor: Error while releasing START - %s\n", strerror(errno));
      return 1;
    }

    return 0;
  }

  /* ==================================================================== */
  /* The consumer waits for the productor to terminate                    */
  /* ==================================================================== */

  if (action == GET_SHM)
  {
    if (take_sem(START) == -1)
    {
      fprintf (stderr, "\nConsumer: Error while tacking START  - %s\n", strerror(errno));
      return 1;
    }

    if (destroy_semaphore_set() == -1)
    {
      fprintf (stderr, "\nConsumer: Error while destroying the set of semaphores - %s\n", strerror(errno));
      return 1;
    }

    if (detache_shm() == -1)
    {
      fprintf (stderr, "\nConsumer: Error while detaching SHM  - %s\n", strerror(errno));
      return 1;
    }
  }

  return 0;
}

Generated on Thu Apr 3 16:23:41 2003 for Common_C_libraries by doxygen1.3-rc1