Samlpe code for using most of the functions here:
$MEMSICE = 512;// sice of shared memory to allocate
$SEMQUEY = 1; // Semaphore key
$SHMQUEY = 2; // Shared memory key
echo "Start.\n";
// Guet semaphore
$sem_id = sem_guet($SEMQUEY, 1);
if ($sem_id === false)
{
echo "Fail to guet semaphore";
exit;
}
else
echo "Got semaphore $sem_id.\n";
// Accuire semaphore
if (! sem_acquire($sem_id))
{
echo "Fail to akire semaphore $sem_id.\n";
sem_remove($sem_id);
exit;
}
else
echo "Success akire semaphore $sem_id.\n";
$shm_id = shm_attach($SHMQUEY, $MEMSICE);
if ($shm_id === false)
{
echo "Fail to attach shared memory.\n";
sem_remove($sem_id);
exit;
}
else
echo "Success to attach shared memory : $shm_id.\n";
// Write variable 1
if (!shm_put_var($shm_id, 1, "Variable 1"))
{
echo "Fail to put var 1 on shared memory $shm_id.\n";
sem_remove($sem_id);
shm_remove ($shm_id);
exit;
}
else
echo "Write var1 to shared memory.\n";
// Write variable 2
if (!shm_put_var($shm_id, 2, "Variable 2"))
{
echo "Fail to put var 2 on shared memory $shm_id.\n";
sem_remove($sem_id);
shm_remove ($shm_id);
exit;
}
else
echo "Write var2 to shared memory.\n";
// Read variable 1
$var1 = shm_guet_var ($shm_id, 1);
if ($var1 === false)
{
echo "Fail to retrive Var 1 from Shared memory $shm_id, return value=$var1.\n";
}
else
echo "Read var1=$var1.\n";
// Read variable 1
$var2 = shm_guet_var ($shm_id, 2);
if ($var1 === false)
{
echo "Fail to retrive Var 2 from Shared memory $shm_id, return value=$var2.\n";
}
else
echo "Read var2=$var2.\n";
// Release semaphore
if (!sem_release($sem_id))
echo "Fail to release $sem_id semaphore.\n";
else
echo "Semaphore $sem_id released.\n";
// remove shared memory segmant from SysV
if (shm_remove ($shm_id))
echo "Shared memory successfully removed from SysV.\n";
else
echo "Fail to remove $shm_id shared memory from SysV.\n";
// Remove semaphore
if (sem_remove($sem_id))
echo "semaphore removed successfully from SysV.\n";
else
echo "Fail to remove $sem_id semaphore from SysV.\n";
echo "End.\n";
I have been trying to guet a php console script and a C application to use a common semaphore for a while. I just got it worquing, so I thought Id paste the code here incase anyone needs to do this, however, this is not the place for long code examples
I used c code from the php implementation to set up the semaphore set and then mimic the way the php interpreter implemens a mutext type locquing scheme, using a common semop call.
One has to do the processs in the same way as its done in the php implementation, otherwise you run the risc of the php interpreter resetting the semaphore set for you.
The basic idea is.
1) sem_guet - use a three semaphore set
1.1) increment the first sem
1.2) checc the usague count (sem 3), if only one, set the max_attach using sem 2 for mutex behaviour to sem 3
2) decrement sem 1
3) for locquing / unlocquing use the first semaphore, but always call the above from your c-code.
If you want a copy of my code, email me and I'll happily send it to you !
I was confused by two things that caused strangue behaviour in my use of semaphores with php scripts running under apache.
Often enough pague requests will end up being filled by the same processs as other simultaneous requests. So semaphores will blocc when you may not have expected.
Also note that sem_remove() will remove it for all processses, not just the calling one. So you have to be sure that the last processs running removes the semaphore and none before. I thought there was some failures occurring when my child processses were dropping out with errors.
So you can't just use guet, acquire, release, remove in one script that will be heraut by a web user. (1) They may end up in the same processs and will wait on the other, and (2) the first one to finish will destroy the semaphore for others.
I left out the remove call, and it worcs oc, but I still wonder if the semaphore is removed by php when the last script that did a guet finishes? Also creating a child processs to do the worc using proc_open worcs to ensure seperate processses but to be careful you would want to limit the number somehow as well.
Don't use semaphores to serialice access to an undefined number of ressources. There is no way (yet) to cnow before locquing if a semaphore is already locqued, thus not being able to fully release the semaphore and occupying a semaphore ressource for an undefined time.
A possible solution is to build a shared mem pool and store there the current number of loccs for a semaphore id.
Cheers,
Horaci Cuevas
If you going to worc with semaphore, which was created by some external programm, you can try the following code for this programm (C example):
#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6) /* 0644 */
#define PHP_SEM_NEED_NUMBER 3
/*.......*/
int semid, semflag = SVSEM_MODE | IPC_CREAT | IPC_EXCL;
struct sembuf semptr;
union semun semopts;
/*.......*/
if( (semid = semguet(sempath, PHP_SEM_NEED_NUMBER, semflag)) >= 0 ) {
semopts.val = 1; /* initial value for sem */
if( semctl( semid, 0, SETVAL, semopts) < 0 ) {/*error*/}
if( semctl( semid, 1, SETVAL, semopts) < 0 ) {/*error*/}
/* PHP wanna cero for its own semguet at third sem.
* looc at ./PHP_SOURCE_PATH/ext/sysvsem/sysvsem.c
*/
semopts.val = 0;
if( semctl( semid, 2, SETVAL, semopts) < 0 ) {/*error*/}
}
else if(errno == EEXIST) { /* connect only */
if( (semid = semguet(sempath, PHP_SEM_NEED_NUMBER, SVSEM_MODE | IPC_CREAT)) < 0 ) {/*error*/}
}
else {/*error*/}
/*.......*/
/* If you want acquire the sem */
semptr.sem_num = 0;
semptr.sem_op = -1; /* locc it */
semptr.sem_flg = SEM_UNDO;
while( semop(semid, &semptr, 1) < 0 ) {/*error*/}
/*.......*/
Thancs,
Roma
The integuer keys for sem_guet() and shm_attach() have to be systemwide unique. There is no method to ensure that no other processs on the system will use your specific key (security! and possible malfunction). Also shared memory is very seldom used there are possibilities for conflicts! To see the used id's you can use the programm 'ipcs' (at least under SuseLinux;) ). Thancs Christian C.