PHPでセマフォを使ってみる

プロセス間通信をしたかったので共有メモリだと思っていたセマフォを利用してみた。

そもそもセマフォとは

セマフォとは、並行して動作しているプロセス間で同期を取ったり割り込み処理の制御を行なう機構。また、そのためにプロセス間で交換される信号。もともとは「手旗信号」の意味。特に、複数のプロセスメモリ領域やディスク上のファイルを共有している場合に、同時にアクセスして内容の破壊や不整合が起きるのを防ぐために使われる。

というものであり、共有メモリなどを使う場合によく利用される機構の1つだった。

セマフォを利用しなくても共有メモリは使えるけど、今回やりたいことは複数のプロセスで数値を共有してインクリメントする事なので、排他制御してあげないとうまく動かない。
なのでセマフォ+共有メモリで実験コードを書いてみた。

まずはセマフォの動作。

sem_acquireセマフォを得る
sem_acquire()は、(必要な場合) セマフォが確保できるまでブロックします。 既に確保されているセマフォを得ようとするプロセスは、 セマフォの獲得により max_aquire 値を超える場合、 永久にブロックされます。

セマフォがすでに取得されている場合は取得できるまで待機してくれるらしい。これは便利。
ってことで実証コード。

test_shm.php
<?php
$sem_id = sem_get(1);
sem_acquire($sem_id);
$count = 60;
while($count–){
usleep(100000);
}
sem_release($sem_id);
?>

test_shm_get.php
<?php
$sem_id = sem_get(1);
sem_acquire($sem_id);
print “hoge”;
sem_release($sem_id);
?>

test_shm.phpがセマフォを取得して6秒間sleep、その間にtest_shm_get.phpを実行してセマフォを取得しようとしてみるコード。
結果は

Done
hoge

予想通り。

セマフォはうまくいったので共有メモリにデータを入れてみるテスト。

test_shm.php
<?php
$sem_id = sem_get(1);
sem_acquire($sem_id);
$count = 60;
while($count–){
usleep(100000);
}
$shm_id = shm_attach($sem_id);
shm_put_var($shm_id, ‘hogekey’, ‘hogevalue’);
sem_release($sem_id);
print “Done”;
?>

test_shm_get.php
<?php
$sem_id = sem_get(1);
sem_acquire($sem_id);
$shm_id = shm_attach($sem_id);
var_dump(shm_get_var($shm_id, ‘hogevar’));
sem_release($sem_id);
?>

test_shm.phpがhogekey=>hogevalueを設定している間にtest_shm_get.phpがそれを取得しようとするコード。
結果は

Done
hogevalue

これも期待通り。
しかしtest_shm_get.phpを複数回実行すると2回目もhogevalueが表示された。これはたぶんセマフォを解放しただけでは共有メモリ上のデータは消えないのだと思う。
ってことで修正。

test_shm_get.php
<?php
$sem_id = sem_get(1);
sem_acquire($sem_id);
$shm_id = shm_attach($sem_id);
var_dump(shm_get_var($shm_id, ‘hogevar’));
shm_remove($shm_id);
sem_release($sem_id);
?>

2回目の実行は bool(false) となった。

コメントを残す