0

ok, im working on an assignment implementing a circular queue (fixed size 15), shared memory, normal producer consumer problem, using three semaphores (one for the queue and one for each process). The objective is to have the producer put the characters from mytest.dat (max 150 chars) into a circular queue, while the consumer pulls them and outputs them to the screen. The exit condition for the consumer is the character * (which should not be output). Currently the producer does pull the information, however the consumer outputs blank characters and then hangs. Any pointers (no pun intended) would be greatly appreciated. After I can get it working as is, I then need to implement the functions in threads, which I believe I can do fairly easily. Am I on the right track as of yet? There arent really any specifications other than what ive said, so I have some play in the implementation. Thank you for your advice and guidance.

#include <stdlib.h> 
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define NUM_ELEM 15 /* Number of elements in shared memory buffer */
#define SEM_MUTEX 0
#define SEM_EMPTY 1
#define SEM_FULL 2

FILE* fp;
int rc, semID, shmID, status, i, x;
char elem;
union semun
{
    int val;
    struct semid_ds *buf;
    ushort *array;
} seminfo;

struct sembuf WaitMutex={SEM_MUTEX, -1, 0};
struct sembuf SignalMutex={SEM_MUTEX, 1, 0};
struct sembuf WaitEmpty={SEM_EMPTY, -1, 0};
struct sembuf SignalEmpty={SEM_EMPTY, 1, 0};
struct sembuf WaitFull={SEM_FULL, -1, 0};
struct sembuf SignalFull={SEM_FULL, 1, 0};
struct shmid_ds shminfo;
char *shmPtr;

void initialize();
void producer();
void consumer();

main()
{

  /* Open file */
  fp= fopen("mytest.dat", "r");

  /* Initialize shared memory and semaphores */
  initialize();

  /* Start a child process and proceed accordingly*/
  if (fork()==0)
  {
    /* Child becomes the consumer */
    consumer();

    /* Child quits after consuming 26 characters */
    exit(0);
  }
  else
  {
    /* Parent becomes the producer */
    producer();

    /* Wait for child to finish */
    wait(&status);

    /* Remove shared memory */
    shmctl(shmID, IPC_RMID, &shminfo);

    /* Remove semaphores */
    semctl(semID, SEM_MUTEX, IPC_RMID, seminfo);

    /* Close file */
    fclose(fp);

    /* Parent is done cleaning up, so now quits */
    exit(0);
  }
}

void initialize()
{

  /* Init semaphores */
  /* Three semaphores (Empty, Full, Mutex) are created in one set */
  semID=semget(IPC_PRIVATE, 3, 0666 | IPC_CREAT);

  /* Init Mutex to one, allowing access to critical section */
  seminfo.val=1;
  semctl(semID, SEM_MUTEX, SETVAL, seminfo);

  /* Init Empty to number of elements in shared memory (circular buffer) */
  seminfo.val=NUM_ELEM;
  semctl(semID, SEM_EMPTY, SETVAL, seminfo);

  /* Init Full to zero, no elements are produced yet */
  seminfo.val=0;
  semctl(semID, SEM_FULL, SETVAL, seminfo);

  /* Init Shared memory */
  shmID=shmget(IPC_PRIVATE, NUM_ELEM, 0666 | IPC_CREAT);
}

void producer()
{
    /* attach shared memory to process */
    shmPtr=(char*)shmat(shmID, 0, SHM_W);

    while((x = fgetc(fp)) != EOF)
    {
        /* Wait(Empty) - pause if no empty spots in circular buffer (i.e. all filled) */
        semop(semID, &WaitEmpty, 1);

        elem = x;
        printf("Produced elem '%c'\n", elem);

        /* Wait(Mutex) - don't touch shared memory while consumer is using it */
        semop(semID, &WaitMutex, 1);

        /* Put element into shared memory buffer (circular buffer) */
        *(shmPtr + (i%NUM_ELEM))=elem;

        /* Signal(Mutex) - allow consumer to access shared memory now */
        semop(semID, &SignalMutex, 1);

        /* Signal(Full) - record one more filled spot in circular buffer */
        semop(semID, &SignalFull, 1);
    }
}

void consumer()
{
    /* attach shared memory to process */
    shmPtr=(char*)shmat(shmID, 0, SHM_R);

    while((elem != EOF))
    {
        /* Wait(Full) - pause if no filled spots in circular buffer (i.e. all empty) */
        semop(semID, &WaitFull, 1);

        /* Wait(Mutex) - don't touch shared memory while producer is using it */
       semop(semID, &WaitMutex, 1);

        /* Get element from the shared memory buffer (circular buffer) */
        elem=*(shmPtr + (i%NUM_ELEM));

        /* Signal(Mutex) - allow producer to access shared memory now */
        semop(semID, &SignalMutex, 1);

        /* Display character */
        printf("Consumed elem '%c'\n", elem);

        /* Signal(Empty) - record one more empty spot in circular buffer */
        semop(semID, &SignalEmpty, 1);
    }
}
1
Contributor
1
Reply
4
Views
4 Years
Discussion Span
Last Post by marc.punzirudu
0

ive modified the code quite a bit, it now compiles using -Wall and -lpthread -lrt, put in some basic error checking, I am still stumped though....any takers or advice?

#define _XOPEN_SOURCE
#include <stdlib.h> 
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/wait.h>

#define NUM_ELEM 15 /* Number of elements in shared memory buffer */
#define SEM_MUTEX 0
#define SEM_EMPTY 1
#define SEM_FULL 2

FILE* fp;
int rc, semID, shmID, status, i, x;
char elem;
union semun
{
    int val;
    struct semid_ds *buf;
    short *array;
} seminfo;

struct sembuf WaitMutex={SEM_MUTEX, -1, 0};
struct sembuf SignalMutex={SEM_MUTEX, 1, 0};
struct sembuf WaitEmpty={SEM_EMPTY, -1, 0};
struct sembuf SignalEmpty={SEM_EMPTY, 1, 0};
struct sembuf WaitFull={SEM_FULL, -1, 0};
struct sembuf SignalFull={SEM_FULL, 1, 0};
struct shmid_ds shminfo;
char *shmPtr;

void initialize();
void producer();
void consumer();

int main()
{

  /* Initialize shared memory and semaphores */
  initialize();

  /* Start a child process and proceed accordingly*/
  if (fork()==0)
  {
    /* Child becomes the consumer */
    consumer();
    exit(0);
  }
  else
  {
    /* Parent becomes the producer */
    producer();

    /* Wait for child to finish */
    wait(&status);

    /* Remove shared memory */
    shmctl(shmID, IPC_RMID, &shminfo);

    /* Remove semaphores */
    semctl(semID, SEM_MUTEX, IPC_RMID, seminfo);

    /* Close file */
    fclose(fp);

    /* Parent is done cleaning up, so now quits */
    return 0;
  }
}

void initialize()
{

  /* Init semaphores */
  /* Three semaphores (Empty, Full, Mutex) are created in one set */
  semID=semget(IPC_PRIVATE, 3, 0666 | IPC_CREAT);

  /* Init Mutex to one, allowing access to critical section */
  seminfo.val=1;
  semctl(semID, SEM_MUTEX, SETVAL, seminfo);

  /* Init Empty to number of elements in shared memory (circular buffer) */
  seminfo.val=NUM_ELEM;
  semctl(semID, SEM_EMPTY, SETVAL, seminfo);

  /* Init Full to zero, no elements are produced yet */
  seminfo.val=0;
  semctl(semID, SEM_FULL, SETVAL, seminfo);

  /* Init Shared memory */
  shmID=shmget(IPC_PRIVATE, NUM_ELEM, 0666 | IPC_CREAT);

  if (shmID == -1)
  {
    perror("shmget failed");
    exit(1);
  }
}

void producer()
{

    /* Open file */
     fp= fopen("mytest.dat", "r");
     if (fp == NULL)
    {
        printf("File not found!\n");
    }

    /* attach shared memory to process */
    shmPtr=(char*)shmat(shmID, 0, SHM_W);

    /* Check for error in shmptr assignment */
    if (shmPtr == (void *)(-1))
    {
       perror("shmat failed in producer");
       exit(1);
    }

    while(x = getchar() != EOF)
    {

    /* Wait(Empty) - pause if no empty spots in circular buffer (i.e. all filled) */
        semop(semID, &WaitEmpty, 1);

        elem = x;
        printf("Produced elem '%c'\n", elem);

        /* Wait(Mutex) - don't touch shared memory while consumer is using it */
        semop(semID, &WaitMutex, 1);

        /* Put element into shared memory buffer (circular buffer) */
        *(shmPtr + (i%NUM_ELEM))=elem;

        /* Signal(Mutex) - allow consumer to access shared memory now */
        semop(semID, &SignalMutex, 1);

        /* Signal(Full) - record one more filled spot in circular buffer */
        semop(semID, &SignalFull, 1);
    }
}

void consumer()
{
    /* attach shared memory to process */
    shmPtr=(char*)shmat(shmID, 0, SHM_R);

    while(elem != '*')
    {
        /* Wait(Full) - pause if no filled spots in circular buffer (i.e. all empty) */
        semop(semID, &WaitFull, 1);

        /* Wait(Mutex) - don't touch shared memory while producer is using it */
     semop(semID, &WaitMutex, 1);

        /* Get element from the shared memory buffer (circular buffer) */
        elem=*(shmPtr + (i%NUM_ELEM));

        /* Signal(Mutex) - allow producer to access shared memory now */
        semop(semID, &SignalMutex, 1);

        /* Display character */
        printf("%c", elem);

        /* Signal(Empty) - record one more empty spot in circular buffer */
        semop(semID, &SignalEmpty, 1);
    }
}
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.