100 likes | 118 Views
Readers and Writers. An introduction to the Linux programming interface for using UNIX semaphores. Proberen and Verlagen. Dijkstra’s invention (1965) Variable s is initialized to a positive value P(s) tests s and, if positive, decrements s; otherwise sleeps until s becomes positive
E N D
Readers and Writers An introduction to the Linux programming interface for using UNIX semaphores
Proberen and Verlagen • Dijkstra’s invention (1965) • Variable s is initialized to a positive value • P(s) tests s and, if positive, decrements s; otherwise sleeps until s becomes positive • V(s) increments s • Can be used to achieve mutual exclusion • Or to enforce an upper limit on the number of simultaneous accesses to a resource
Wait and Signal • Dijkstra’s P(s) and V(s) operations often are called ‘semWait()’ and ‘semSignal()’ struct semaphore { int count; queue_t q; }; void semWait( struct semaphore s ) { if ( --s.count < 0 ) { block( task ); enqueue( task, s.q ); } } void semSignal( struct semaphore s ) { if ( ++s.count >= 0 ) { dequeue( task, s.q ); unblock( task ); } }
Readers and Writers • A data buffer is shared among a number of separate processes • Some processes want to read the buffer, and other processes want to write to the buffer • Multiple readers may read it simultaneously • Only one writer at a time can write to the buffer • While a writer is writing to the buffer, no reader may read from it
Semaphore sets • You use the ‘semget()’ function to create a new semaphore set within the kernel (and aquire a ‘handle’ to it for later reference) • You use the ‘semctl()’ function to inspect or modify the semaphore value(s) for the semaphores in your semaphore set • Use ‘semat()’ and ‘semdt()’ to attach and detach the semaphore set to your process
UNIX kernel structures struct sem current value of the semaphore counter pid of the most recent task to access it counts tasks awaiting semval >= current counts tasks awaiting semval == 0 semval sempid semncnt semznt
A ‘semaphore set’ descriptor struct sem array[ ] nsems = 3 struct semid_ds sem_perm *sem_base sem_nsems sem_otime sem_ctime
Semaphore ‘actions’ • You use the ‘semop()’ function to request the kernel to perform one or more ‘actions’ on semaphores in your semaphore set • Such actions will be performed atomically • The types of actions include incrementing and decrementing a semaphore’s counter, as well as ‘waiting’ until the semaphore’s value is increased
A client-and-server demo • Our ‘lottery.cpp’ program implements a ‘server’ which writes to shared memory • Our ‘gambler.cpp’ program implements a ‘client’ which reads from shared memory • A semaphore set with two semaphores is used for coordinating the reads and writes
In-class exercise • Can you implement a modification of the ‘gambler.cpp’ client-program which forks multiple separate reader-processes using randomly generated ‘bets’ in order to try and ‘win’ the lottery (i.e., by guessing the winning number-combination)? • How many times will you need to ‘fork()’ in order to have a better-than-even chance at winning?