Download | Plain Text | Line Numbers
/* define SUSv2 standard */
#define _XOPEN_SOURCE 500
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#define NUM_CHILDS 10
#define SIZE_RINGBUF 50
void P(int semaphoresId,int semaphoreNr);
void V(int semaphoresId,int semaphoreNr);
void child_write();
void child_read();
typedef struct
{
unsigned buf[SIZE_RINGBUF];
unsigned insert;
unsigned remove;
} ringbuffer;
ringbuffer *ringbuf;
int main(int argv, char** argc)
{
int shmid, semid, i, pid;
int childs[NUM_CHILDS];
struct sembuf sbuf;
/* create shared memory */
shmid = shmget(IPC_PRIVATE, sizeof(ringbuffer), IPC_CREAT | 0600);
/* create + initialize semaphor */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = 0;
semop(semid, &sbuf, 1);
/* attach and initialize shared memory */
ringbuf = shmat(shmid, NULL, 0);
ringbuf->insert = ringbuf->remove = 0;
/* create and start childs */
for(i = 0; i < NUM_CHILDS; i++)
{
if((pid = fork()) == 0)
{
/* child */
while(1)
{
P(semid, 0);
if (i % 2 == 0)
child_write();
else
child_read();
V(semid, 0);
/*usleep(10000);*/
}
/* although this will never be reached this would be the correct shutdown behaviour */
shmdt(ringbuf);
exit(1);
}
else
{
/* parent */
childs[i] = pid;
}
}
/* wait for any key press */
getchar();
/* send sigterm to all childs */
for(i = 0; i < NUM_CHILDS; i++)
{
kill(childs[i], SIGTERM);
int status;
waitpid(childs[i], &status, 0);
}
/* remove semaphor */
semctl(semid, 0, IPC_RMID);
/* detach and remove shared memory */
shmdt(ringbuf);
shmctl(shmid, 0, IPC_RMID);
return 1;
}
void child_write()
{
unsigned num;
struct timeval tp;
if (ringbuf->buf[ringbuf->insert] != 0)
return;
/* srand + some entropy */
gettimeofday(&tp, NULL);
srand(tp.tv_sec + tp.tv_usec + getpid());
num = 1 + (unsigned) (RAND_MAX * (rand() / (RAND_MAX + 1.0)));
ringbuf->buf[ringbuf->insert] = num;
printf("[%d] W [%u] = %u\n", getpid(), ringbuf->insert, num);
ringbuf->insert++;
if (ringbuf->insert >= SIZE_RINGBUF)
ringbuf->insert = 0;
}
void child_read()
{
unsigned num;
num = ringbuf->buf[ringbuf->remove];
if (num == 0)
return;
ringbuf->buf[ringbuf->remove] = 0;
printf("[%d] R [%u] = %d\n", getpid(), ringbuf->remove, num);
ringbuf->remove++;
if (ringbuf->remove >= SIZE_RINGBUF)
ringbuf->remove = 0;
}
void P(int semaphoresId,int semaphoreNr)
{
struct sembuf semaphoreOperation;
semaphoreOperation.sem_num = semaphoreNr;
semaphoreOperation.sem_op = -1;
semaphoreOperation.sem_flg = 0;
semop(semaphoresId, &semaphoreOperation, 1);
}
void V(int semaphoresId,int semaphoreNr)
{
struct sembuf semaphoreOperation;
semaphoreOperation.sem_num = semaphoreNr;
semaphoreOperation.sem_op = 1;
semaphoreOperation.sem_flg = 0;
semop(semaphoresId, &semaphoreOperation, 1);
}