/* define SUSv2 standard */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include #include #include #include #include #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); }