2009-06-25 6 views
1

J'ai un programme CGI Perl qui s'exécute sous mod_perl. Dans le programme, je voudrais empêcher une ressource d'accéder par plusieurs processus en même temps.Interprocess Mutex En Perl

# Semaphore Initialization Code 
# 10023 is unique id, and this id will be same across different apache process. 
# 1, Only one semaphore being created. 
# 0722, as all process will be execute under apache account. Hence, they will all having '7' privilege. 
my $sem = new IPC::Semaphore(10023, 1, 0722 | IPC_CREAT); # Code(1) 
# Set 0th (one and only one) semaphore's value to 1, As I want to use this semaphore as mutex. 
$sem->setval(0, 1);          # Code(2) 

Le problème est:

  1. Comment puis-je faire le code (1) créer une nouvelle sémaphores que lorsque les sémaphores si l'identifiant 10023 n'a jamais été créé auparavant, soit par même processus ou d'autres processus ?
  2. Comment exécuter le code (2) SEULEMENT la première fois que je crée le sémaphore avec l'ID 10023? Un sémaphore doit être initialisé UNIQUEMENT.

Une autre approche consiste à créer un fichier vide à des fins de verrouillage. Cependant, cela se traduira par des milliers de fichiers temporaires. link text

+1

Pourquoi des milliers de fichiers temporaires? Si vous prévoyez d'utiliser un sémaphore, vous utiliseriez un seul fichier. – ysth

+0

Je vais utiliser sémaphore par client de base. Comme il est possible pour un client d'envoyer plusieurs requêtes HTTP en même temps. –

Répondre

4

Ajout du drapeau IPC_EXCL provoque l'semget sous-jacente à créer une nouvelle sémaphores ou échouer. Vous pouvez l'utiliser pour obtenir l'effet que vous voulez.

Cela devrait fonctionner pour vous:

#Attempt to create (but not get existing) semaphore 
my $sem = IPC::Semaphore->new(10023, 1, 0722 | IPC_CREAT | IPC_EXCL); 
if ($sem) { 
    #success, semaphore created, proceed to set. 
    print "new semaphore\n"; 
    $sem->setval(0, 1); 
} 
else { 
    #obtain the semaphore normally 
    print "existing semaphore\n"; 
    $sem = IPC::Semaphore->new(10023, 1, 0722); #no IPC_CREAT here 
    die "could not obtain semaphore?" unless $sem; 
} 
+0

Au lieu d'utiliser number (10023, 10024) pour identifier l'unicité du sémaphore, peut-on utiliser string (helloworld, goodbyeworld)? –

+0

Ce que vous devriez probablement utiliser est ftok (http://linux.die.net/man/3/ftok), mais notez que seulement 8 bits de proj_id sont utilisés – Hasturkun

+0

Merci! Je vais l'essayer une fois que j'aurai accès à la machine. Une chose est, quand dois-je appeler $ sem-> supprimer? Au départ, je prévois de l'appeler END {#inrease counter à un. #remove sémaphore du système ???} block. Cependant, si je supprime un sémaphore du système alors qu'un autre processus attend le verrou du sémaphore, y a-t-il un effet secondaire (l'exclusion mutuelle va se rompre, soudainement tout le processus en attente peut saisir la ressource). N'est-ce pas, dois-je ignorer «supprimer» appel? Cela entraînera-t-il une fuite de ressources système? –