Hey all,
I am relatively new to C programming and need to write a program that uses semaphores to control access to shared memory that places items into a circular buffer. The problem I have is one where the consumer runs out of things to consume and the producer doesn't wake up to place anything new into the buffer. I have the following code, which gives the output below it. I have been looking at this now for days and just seem to be going around in circles. Ay help would be appreciated.
Thanks,
Terry
Output:Code:#define _SVID_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <semaphore.h> #include <fcntl.h> #include <sys/uio.h> #include <sys/shm.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #define BUFFER_SIZE 10 #define ERROR_CHAR (-1) #define MAX_FILE_SIZE 256 #define TRUE 1 #define FALSE 0 void buffer_char(char *c); char* unbuffer_char(void); typedef struct { char file_path[BUFFER_SIZE][MAX_FILE_SIZE]; int head; int tail; sem_t full; sem_t empty; sem_t mutex; } Buffer; Buffer *buffer_ptr; int main(int argc, char** argv) { int shmid; pid_t prod_pid, con_pid; /* shmid is the id of the shared memory address for our buffer */ shmid = shmget(IPC_PRIVATE, getpagesize(), IPC_CREAT | 0666); /* get a pointer to our buffer in shared memory */ buffer_ptr = (Buffer*) shmat(shmid, NULL, 0); /* initialise the buffer */ buffer_ptr->head = 0; buffer_ptr->tail = 0; /* initialise our semaphores (2nd param 1 means shared betweeen processes */ sem_init(&buffer_ptr->empty, 1, BUFFER_SIZE); sem_init(&buffer_ptr->full, 1, 0); sem_init(&buffer_ptr->mutex, 1, 1); /* spawn our child processes */ prod_pid = fork(); if (prod_pid == 0) { /* this is the producer process */ int i; char items[15][10] = {"File 1", "File 2", "File 3", "File 4", "File 5", "File 6", "File 7", "File 8", "File 9", "File 10", "File 11", "File 12", "File 13", "File 14", "File 15"}; for (i = 0; i < 15; i++) { sem_wait(&buffer_ptr->empty); sem_wait(&buffer_ptr->mutex); printf("Buffering %s\n", items[i]); buffer_char(items[i]); sem_post(&buffer_ptr->mutex); sem_post(&buffer_ptr->full); } exit(0); } con_pid = fork(); if (con_pid == 0) { /* this is the consumer process */ while (TRUE) { sem_wait(&buffer_ptr->full); sem_wait(&buffer_ptr->mutex); printf("Unbeffering %s\n", unbuffer_char()); sem_post(&buffer_ptr->mutex); sem_post(&buffer_ptr->empty); } exit(0); } if (prod_pid != 0 && con_pid != 0) { /* this is the main process so wait here for both processes to finish before closing out and finishing */ wait(prod_pid); wait(con_pid); printf("************************************"); /* detach the shared memory and deallocate the memory segment */ shmdt(&buffer_ptr); shmctl(shmid, IPC_RMID, 0); /* finally, close the signature file */ return (EXIT_SUCCESS); } } void buffer_char(char* c) { /* Use modulo as a trick to wrap around the end of the buffer back to the beginning */ if ((buffer_ptr->tail + 1) % BUFFER_SIZE != buffer_ptr->head) { strcpy(buffer_ptr->file_path[buffer_ptr->tail], c); buffer_ptr->tail = (buffer_ptr->tail + 1) % BUFFER_SIZE; } } char* unbuffer_char(void) { if (buffer_ptr->tail != buffer_ptr->head) { char *temp = buffer_ptr->file_path[buffer_ptr->head]; buffer_ptr->head = (buffer_ptr->head + 1) % BUFFER_SIZE; printf("Head: %d\n", buffer_ptr->head); printf("Tail: %d\n", buffer_ptr->tail); return (temp); } else { printf("Problem is here!\n"); printf("Head: %d\n", buffer_ptr->head); printf("Tail: %d\n", buffer_ptr->tail); } }
Code:Buffering File 1 Buffering File 2 Buffering File 3 Buffering File 4 Buffering File 5 Buffering File 6 Buffering File 7 Buffering File 8 Buffering File 9 Buffering File 10 Head: 1 Tail: 9 Unbeffering File 1 Head: 2 Tail: 9 Unbeffering File 2 Head: 3 Tail: 9 Unbeffering File 3 Head: 4 Tail: 9 Unbeffering File 4 Head: 5 Tail: 9 Unbeffering File 5 Head: 6 Tail: 9 Unbeffering File 6 Head: 7 Tail: 9 Unbeffering File 7 Head: 8 Tail: 9 Unbeffering File 8 Head: 9 Tail: 9 Unbeffering File 9 Problem is here! Head: 9 Tail: 9



LinkBack URL
About LinkBacks


