English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

PHPプロセス通信の基礎シグナルとシェアメモリ通信

プロセス間の実行順序が決まっていないため、これは複雑なプロセススケジュールアルゴリズムに依存しています。したがって、複数のプロセスが同時に共有メモリにアクセスする可能性があり、予期せぬエラーが発生する可能性があります。シグナルの名前は奇妙なものですが、英語の意味を見ると非常に理解しやすいです。

semaphore 英[ˈseməfɔ:(r)] vt. 信号を出す,旗を振る;

指揮官のような役割です。

次の仮コードシグナルの使用を見てみましょう。

1、シグナルのユニーク識別子の作成

$ftok = ftok(__FILE__, 'a');

2、シグナルリソースIDの作成

$sem_resouce_id = sem_get($ftok);

3、シグナルの受信

sem_acqure($sem_resource_id);

4、シグナルの解放

sem_release($sem_resource_id);

5、シグナルの破棄

sem_remove($sem_resource_id);

不文雅な例を举いて、シグナルの生活での使用法を理解しやすくします。理解した後、プログラミングの分野に適用できます。
会社にはトイレが1つしかありません。トイレを使う際には、ロック(シグナル)を取得して、トイレが使用中であることを示します。以下のコードです:

sem_acqure($sem_resource_id);

従業員がトイレを使い終わったら、ロックを解除し、ロック(シグナル)を解放して、他の人が使用できることを示します。以下のコードです:

sem_release($sem_resource_id);

シンプルなロックを使うことで、現在のトイレ(共有メモリ)が使用可能かどうかを知ることができます。この例は不適切ですが、問題を説明するのに役立ちます。このブログも匂いがするブログですが、本当に大変でした。。。。以下にサンプルコードを示します:

<?php
//共有メモリ領域の作成
$shm_key = ftok(__FILE__, 'a');
$shm_id = shm_attach($shm_key, 1024, 0755);
//var_dump($shm_id);die(); resource(4) of type (sysvshm)
const SHARE_KEY = 1;
$child_list = [];
//信号量の追加
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);
//$signal resource(5) of type (sysvsem)
for ($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  exit("Fork fail!".PHP_EOL); -1) {
    elseif ($pid == 0) {
  }
    //シグナルマネージャーを取得
    sem_acquire($signal);
    if (shm_has_var($shm_id,SHARE_KEY)) {
      $count = shm_get_var($shm_id, SHARE_KEY);
      $count++;
      //ビジネス処理のシミュレーション
      $sec = rand(1, 3);
      sleep($sec);
      shm_put_var($shm_id, SHARE_KEY, $count);
    }
      $count = 0;
      $sec = rand(1, 3);
      sleep($sec);
      shm_put_var($shm_id, SHARE_KEY, $count);
    }
    echo "child process: ".getmypid()." is writing! now count is: $count ".PHP_EOL;
    //シグナルマネージャーを解放
    sem_release($signal);
    exit("child process".getmypid()."end".PHP_EOL);
  }
    $child_list[] = $pid;
  }
}
while (count($child_list) > 0) {
  foreach ($child_list as $key => $pid) {
    $status = pcntl_waitpid($pid, $status);
    if ($status > 0 || $status == -1) {
      unset($child_list[$key]);
    }
  }
  sleep(1);
}
$count = shm_get_var($shm_id, SHARE_KEY);
echo " $count  ".PHP_EOL;
//シグナルマネージャーを破壊
sem_remove($signal);
shm_remove($shm_id);
shm_detach($shm_id);