4

そのような状況はいつ発生しますか?

インターポセス ロック ( pcntl 拡張子を使用) に共有メモリとセマフォを使用している場合は、セマフォと共有メモリ セグメントのライフ サークルに注意する必要があります。たとえば、バックグラウンド ワーカー アプリケーションを作成し、ジョブ処理にマスター プロセスと子プロセス (フォークされた) を使用するとします。共有メモリとセマフォを使用することは、それらの間の IPC に適しています。またRAII、shm_xxx および sem_xxx のクラス ラッパーと同様に、php 関数も良いアイデアのように見えます。

class Semaphore
{
     private $file;

     private $sem;

     public function __construct()
     {
        $this->file = tempnam(sys_get_temp_dir(), 's');
        $semKey = ftok($this->file, 'a');

        $this->sem = sem_get($semKey, 1); //auto_release = 1 by default
     }

     public function __destruct()
     {
         if (is_resource($this->sem) {
            sem_remove($this->sem);
         }
     }

     ....
}

良い選択ではありません-フォークの後、親プロセスに1つのインスタンスと子プロセスに1つのインスタンスがあります。そして、それらのいずれかのデストラクタはセマフォを破壊します。

なぜ重要か

ほとんどの Linux システムには、共有メモリ数のセマフォに関する制限があります。セマフォの多くの共有メモリ セグメントを作成および削除するアプリケーションがある場合、プロセスのシャットダウン時に自動的に解放されるまで待つことはできません。

質問

を使用すると、 shmctlを使用сできます。削除するセグメントをマークします。実際の削除自体は、現在セグメントに接続されている最後のプロセスがセグメントを適切に切断したときに発生します。もちろん、現在セグメントに接続されているプロセスがない場合、削除はすぐに行われます。単純な参照カウンターのように機能します。しかし、phpは実装していません。IPC_RMIDshmctl

もう 1 つの戦略 - マスター プロセスのデストラクタでのみセマフォを破棄します。

class Semaphore
{
     ... 
     private $pid;

     public function __construct()
     {
        $this->pid = getmypid();
        ...
     }

     public function __destruct()
     {
         if (is_resource($this->sem) && $this->pid === getmypid()) {
            sem_remove($this->sem);
         }
     }
     ....
}

それで、質問は

  1. PHPでIPC_RMIDを使用する方法はありますか?
  2. このような場合、どのような戦略を使用する必要がありますか? マスター プロセスのみで破棄しますか? 他のケース?
4

1 に答える 1