5.7.1 Problem
5.7.2 Solution
Store the data in a shared memory segment, and guarantee exclusive access to the shared
memory with a semaphore:
$semaphore_id = 100;
$segment_id = 200;
// get a handle to the semaphore associated with the shared memory
// segment we want
$sem = sem_get($semaphore_id,1,0600);
// ensure exclusive access to the semaphore
sem_acquire($sem) or die("Can't acquire semaphore");
// get a handle to our shared memory segment
$shm = shm_attach($segment_id,16384,0600);
// retrieve a value from the shared memory segment
$population = shm_get_var($shm,'population');
// manipulate the value
$population += ($births + $immigrants - $deaths - $emigrants);
// store the value back in the shared memory segment
shm_put_var($shm,'population',$population);
// release the handle to the shared memory segment
shm_detach($shm);
// release the semaphore so other processes can acquire it
sem_release($sem);
5.7.3 Discussion
A shared memory segment is a slice of your machine's RAM that
different processes (such as the multiple web server processes that handle
requests) can access. A semaphore makes sure that the different processes don't
step on each other's toes when they access the shared memory segment. Before a
process can use the segment, it needs to get control of the semaphore. When it's
done with the segment, it releases the semaphore for another process to grab.
To get control of a semaphore, use sem_get( ) to find the semaphore's ID. The first argument to
sem_get( ) is an integer semaphore key. You can make the key any
integer you want, as long as all programs that need to access this particular
semaphore use the same key. If a semaphore with the
specified key doesn't already exist, it's created, the maximum number of
processes that can access the semaphore is set to the second argument of
sem_get( ) (in this case, 1), and the semaphore's permissions
are set to sem_get( )'s third argument (0600). These
permissions work just like file permissions, so 0600 means that the
user that created the semaphore can read it and write to it. In this context,
user doesn't just mean the process that created the semaphore but any process
with the same user ID. Permissions of 0600 should be appropriate for
most uses, in which web server processes run as the same user.
sem_get( ) returns an identifier that points to the
underlying system semaphore. Use this ID to gain control of the semaphore with
sem_acquire( ). This function waits until the
semaphore can be acquired (perhaps waiting until other processes release the
semaphore) and then returns true. It returns false on error.
Errors include invalid permissions or not enough memory to create the semaphore.
Once the semaphore is acquired, you can read from the shared memory segment.
First, establish a link to the particular shared memory segment
with shm_attach( ) . As
with sem_get( ), the first argument to shm_attach( ) is an
integer key. This time, however it identifies the desired segment, not the
semaphore. If the segment with the specified key doesn't exist, the other
arguments create it. The second argument (16384) is the size in bytes
of the segment, and the last argument (0600) are the permissions on the
segment. shm_attach(200,16384,0600) creates a 16K shared memory segment
that can be read from and written to only by the user who created it. The
function returns the identifier you need to read from and write to the shared
memory segment.
After attaching to the segment, pull variables out of it with
shm_get_var($shm, 'population'). This looks in
the shared memory segment identified by $shm and retrieves the value of
the variable called population. You can store any type of variable in
shared memory. Once the variable is retrieved, it can be operated on like other
variables. shm_put_var($shm,'population',$population) puts the value of $population back into the shared
memory segment as a variable called population.
You're now done with the shared memory statement. Detach from
it with shm_detach( ) and
release the semaphore with sem_release( ) so another process can use
it.
Shared memory's chief advantage is that
it's fast. But since it's stored in RAM, it can't hold too much data, and it
doesn't persist when a machine is rebooted (unless you take special steps to
write the information in shared memory to disk before shutdown and then load it
into memory again at startup). Also, shared memory is not available on Windows.