#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>
/* NOTE: Need to remove excess spaces in between angle brackets in the above. */
#define NUM_ELEM 10 /* Number of elements in shared memory buffer */
#define SEM_MUTEX 0
#define SEM_EMPTY 1
#define SEM_FULL 2
int rc, semID, shmID, status, i;
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()
{
/* 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();
/* Returns after producing 26 characters */
/* Wait for child to finish */
wait(&status);
/* Remove shared memory */
shmctl(shmID, IPC_RMID, &shminfo);
/* Remove semaphores */
semctl(semID, SEM_MUTEX, IPC_RMID, seminfo);
/* 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);
for(i=0; i < 26; i++)
{
/* Wait(Empty) - pause if no empty spots in circular buffer (i.e. all filled) */
semop(semID, &WaitEmpty, 1);
/* Produce element. Example element are chars 'a'-'z' */
elem='a'+i;
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);
for(i=0; i < 26; i++)
{
/* 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);
}
}