Producer Consumer Problem in C using Semaphores and Shared Memory
Written by Abhishek Ghosh
The classic bounded-buffer problem can be implemented using a variety of synchronization mechanisms. One may use Monitors, disable scheduling, or even disable scheduling including interrupts to ensure critical region safety. A common mechanism is to use semaphores. I have implemented this classic problem in C using semaphores and shared memory. I have used the pthread library instead of sys/sem.h. However I have not used any threads and just used the operations for sem_t type defined in semaphore.h from the pthread library. Inter process communication is done between heavyweight processes using shared memory.
The source C file can be downloaded here.
Executable generation process :
gcc procon5.c -o procon5 -lpthread
Executable file can be downloaded here. (to run : ./procon5 )
Explanation :
The master process starts by allocating shared memory for the buffer and other shared variables. The buffer is taken s an array based stack.
The functions used for this are :
shmget() : to allocate shared memory.
shmat() : to attach pointers to shared memory for performing operations on them.
The master process then initializes semaphores of type sem_t (defined in semaphore.h) using
sem_init() : used to initialize sem_t semaphore (provided in pthread.h). On providing the second argument as non zero, the semaphore can be used in IPC using shared memory.
Then it initializes the following shared variables :
len - Length of input string entered.
pr_countp - Number of items produced.
co_countp - Number of items consumed.
buff_top - Poition of top indicator in buffer.
run - Control variable, required to be set for process execution.
After determining number of producers and consumers desired from command line user input, the master process goes on to create the required number of producers and consumers using the fork() call in a loop. The return value from the fork call is used to control program flow beyond this instruction. On returning a non‐zero, positive value the process continues as parent and the pid is stored in an array of children_pids. On returning 0, a produce() or consume() procedure is called based on previous user input. The produce() and consume() procedures do not start actual execution at this time.
After all the producer and consumer processes have been created , the shared variable ‘run’ is set to 1, in order to start actual execution of processes.
The master process then waits for all the child processes to terminate using waitpid().
Finally, the space for shared memory & semaphores is deallocated and the pointers are detached, using shmdt(),shmctl() & sem_destroy().
Semaphores –
Mutex – For mutual exclusion while performing actual operation on shared memory.
Empty – For counting number of empty slots and blocking consumers if 0 empty slots.
Full – For counting full slots and blocking producers when buffer is full.
Producer Process –
If (pr_countp > len)
Then Exit (all items have been produced)
Else If (buff_top < buff_size && run == 1)
Wait (empty)
Wait (mutex)
Produce item and put into buffer
Signal (mutex)
Signal (full)
Consumer Process –
If (co_countp > len)
Then Exit (all items have been consumed)
Else If (buff_top < buff_size && run == 1)
Wait (full)
Wait (mutex)
Produce item and put into buffer
Signal (mutex)
Signal (empty)

Articles














Comments
http://wahid311.blogspot.com" rel="nofollow" target="_blank">http://wahid311.blogspot.com