Readers and Writers An introduction to the Linux programming interface for using

Download Report

Transcript Readers and Writers An introduction to the Linux programming interface for using

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
semval
sempid
semncnt
semznt
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
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?