PHP でのプロセス間通信の実装
Qiu Wenyu
この記事では、PHP4 環境でプロセス間通信メカニズム - IPC (Inter-Process-Communication) を使用する方法について説明します。 。この記事で説明するソフトウェア環境は linux php4.0.4 以降です。まず、PHP4 と UNIX がインストールされていることを前提としています。php4 で共有メモリとセマフォを使用するには、php4 プログラムのコンパイル時に 2 つの拡張モジュール shmop と sysvsem をアクティブにする必要があります。
実装方法:PHPのセットアップ(configure)時に以下のオプションを追加します。
--enable-shmop --enable-sysvsem
これにより、PHP システムが関連する IPC 関数を処理できるようになります。
IPCとは何ですか?
IPC (プロセス間通信) は、同じホスト上の異なるプロセスが相互に通信する方法を提供する Unix 標準通信メカニズムです。 IPC には、共有メモリ、セマフォ、メッセージ キューという 3 つの基本的な処理メカニズムがあります。この記事では、主に共有メモリとセマフォの使用について説明します。メッセージキューについては、近いうちに具体的に紹介する予定です。
PHP での共有メモリ セグメントの使用
異なる処理プロセス間で共有メモリを使用することは、異なるプロセス間の相互通信を実現する良い方法です。 1 つのプロセスで共有メモリに情報を書き込むと、他のすべてのプロセスも書き込まれたデータを参照できます。とても便利です。 PHP の共有メモリを利用すると、異なるプロセスが同じ PHP スクリプトを実行したときに異なる結果を得ることができます。または、同時に実行されている PHP の数に対するリアルタイム クエリを実装するなど。
共有メモリを使用すると、2 つ以上のプロセスが特定のストレージ領域を共有できます。クライアントとサーバーの間でデータをコピーする必要がないため、これは最も高速なタイプの IPC です。共有メモリを使用する唯一のコツは、複数のプロセスが特定のメモリ領域に同時にアクセスすることです。
共有メモリセグメントを作成するにはどうすればよいですか?次のコードは、共有メモリの作成に役立ちます。
$shm_id = shmop_open($key, $mode, $perm, $size);
各共有メモリ セグメントには一意の ID があることに注意してください。PHP では、shmop_open は作成された共有メモリの ID を保存します。が返されるので、ここでは $shm_id を使用して記録します。 $key は、共有メモリ セグメントを論理的に表す Key 値です。異なるプロセスは、同じキー ID を選択する限り、同じストレージ セグメントを共有できます。 $mode は、共有メモリ セグメントの使用方法を指定するキー ID として文字列 (ファイル名など) のハッシュ値を使用するのが一般的です。これは新規作成であるため、値は「c」、つまり作成を意味します。作成した共有メモリにアクセスする場合は、アクセスを意味する「a」を使用してください。 $perm パラメータは、アクセス許可を 8 進形式で定義します。許可の定義については、UNIX ファイル システムのヘルプを参照してください。 $size は共有メモリのサイズを定義します。 fopen (ファイル処理) に少し似ていますが、ファイル処理と同じと考えるべきではありません。これについては後の説明で少し説明します。
例:
$shm_id = shmop_open(0xff3, "c", 0644, 100);
ここでは、共有メモリ セグメント キー値 0xff3 –rw-r—r— 形式、サイズ 100 バイトを開きます。 。
既存の共有メモリセグメントにアクセスする必要がある場合は、shmop_open を呼び出すときに 3 番目と 4 番目のパラメータを 0 に設定する必要があります。
IPC 動作ステータスのクエリ
Unix では、コマンド ライン プログラム ipcs を使用して、システム内のすべての IPC リソースのステータスをクエリできます。ただし、一部のシステム要件ではスーパーユーザーが実行する必要があります。下の図は、ipcs の実行結果の一部です。
上の図では、システムに 4 つの共有メモリ セグメントが表示されています。4 番目のキー値は 0x00000ff3 で、先ほど実行した PHP プログラムによって作成されたものであることに注意してください。 ipcs の使用方法については、UNIX ユーザー マニュアルを参照してください。
共有メモリを解放する方法
共有メモリを解放する方法は、PHP コマンドを呼び出すことです: shmop_delete($id)
shmop_delete($id);
$id は保存された shmop_op の戻り値です。 shmop_open を呼び出すことによって。もう 1 つの方法は、UNIX 管理コマンド
ipcrm id を使用することです。この ID は、プログラム内の $id とは異なります。ただし、ipcrm を使用して共有メモリ セグメントを直接削除すると、この状況を認識していない他のプロセスが、存在しないこの共有メモリを参照するときに予期しないエラー (多くの場合、好ましくない結果を伴う) を引き起こす可能性があることに注意してください。
共有メモリの使用 (読み取りと書き込み) 方法
以下の関数を使用して共有メモリにデータを書き込みます
int shmop_write (int shmid, string data, int offset)
ここで shmid は次のように返されますshmop_open ハンドル。 $Data 変数には、保存するデータが保存されます。 $offset は、共有メモリの先頭から最初のバイトを書き込む位置(0 から始まります)を記述します。
読み取り操作は次のとおりです:
string shmop_read (int shmid, int start, int count)
同様に、$shmid、開始オフセット (0 から開始)、および合計読み取り数を指定します。結果の文字列を返します。このようにして、共有メモリ セグメントをバイト配列として扱うことができます。いくつか読んだり、いくつか書いたりできるので、とても便利です。
マルチプロセスの問題についての考察
さて、別のプロセスで、別のプロセスで 2つのプロセスによって書き込まれたデータは、順番にランダムに混在して出現します。これは明らかに容認できません。この問題を解決するには、相互排他メカニズムを導入する必要があります。相互排他メカニズムについては、多くのオペレーティング システムの教科書で詳しく説明されているため、ここでは繰り返しません。相互排除メカニズムを実装する最も簡単な方法は、セマフォを使用することです。セマフォは、プロセス間通信 (IPC) の別の方法であり、他の IPC メカニズム (パイプライン、FIFO、メッセージ キュー) とは異なります。複数のプロセスによる共有データの保存を制御するために使用されるカウンターです。同様に、ipcs および ipcrm を使用して、セマフォのステータスを照会し、セマフォを削除できます。 PHP では、次の関数を使用して新しいセマフォを作成し、セマフォへのハンドルを返すことができます。キーが指すセマフォがすでに存在する場合、sem_get はセマフォを操作するためのハンドルを直接返します。
int sem_get (int key [, int max_acquire ][, int perm]])
$max_acquire は、シグナルが解放されるのを待たずに、最大複数のプロセスを使用して同時にシグナルに入力できることを示します(つまり、同時に処理できるプロセスの最大数は、リソースのプロセスの数です。通常、値は 1 です)。 $perm はアクセス許可を指定します。
セマフォの所有に成功したら、それに対してできることは 2 つだけです: 要求と解放です。リリース操作を実行すると、システムは信号値を 1 つ減らします。 0未満の場合は0に設定してください。要求された操作を実行すると、システムはシグナル値を 1 つ増やします。その値が設定された最大値よりも大きい場合、システムは他のプロセスが最大値未満の値に解放されるまで処理プロセスを一時停止します。通常の状況では、最大値は 1 に設定されているため、プロセスがリクエストを取得すると、後続の他のプロセスはそのリクエストがミューテックス領域から出るまで待機し、セマフォを解放してからミューテックス領域に入って排他モードに設定します。同時に。このようなセマフォは、バイナリ セマフォと呼ばれることがよくあります。もちろん、初期値が正の数値であれば、それは共有アプリケーションで使用できる共有リソース ユニットの数を示します。
アプリケーションおよびリリース操作の PHP 形式は次のとおりです。
int sem_acquire (int sem_identifier) application
int sem_release (int sem_identifier) release
ここで、sem_identifier は戻り値 (ハンドル) ) sem_get の呼び出し。
相互排他プロトコルの簡単な例
以下は非常に簡単な相互排他操作手順です。
$semid=sem_get(0xee3,1,0666);
$shm_id = shmop_open(0xff3, "c", 0644, 100);
sem_acquire($semid); // apply
/* クリティカルセクションを入力*/
ここで、共有メモリが処理されます
sem_release($semid)//Release
ご覧のとおり、実装は相互排除の方法は非常に簡単です。クリティカル セクションに入るために適用し、クリティカル セクションのリソースを操作し (共有メモリの変更など)、クリティカル セクションを終了して信号を解放します。これにより、2 つのプロセスが同じタイム スライス内の同じ共有メモリ上で動作することが不可能になります。セマフォ メカニズムにより、タイム スライスに入ることができるのは 1 つのプロセスだけであることが保証されるため、他のプロセスは、現在処理されているプロセスが完了するまで待ってから入る必要があります。
クリティカル セクションは通常、同時に複数のプロセスによる同時処理を許可しないコード セグメントを指します。
PHP では、セマフォが占有しているセマフォは同じプロセスによって解放される必要があることに注意してください。一般的なシステムでは、プロセスは他のプロセスが占有しているシグナルを解放できます。クリティカル セクションのコードを作成するときは、A が B を待ち、B が A を待つというデッドロック状況を避けるために、リソースの割り当てを慎重に設計する必要があります。
使用法
IPC は広く使用されています。たとえば、説明された複雑な設定ファイルや特定のユーザー設定などを異なるプロセス間で保存して、処理の重複を回避します。また、共有メモリ テクノロジを使用して、多数の PHP スクリプトが参照する必要がある大きなファイルを共有メモリに配置しました。これにより、Web サービスの速度が大幅に向上し、いくつかのボトルネックが解消されました。用途としては、チャットルームやマルチキャストなどがあります。 IPC の力はあなたの想像力にかかっています。この記事が少しでもあなたのお役に立てれば光栄です。この魅力的なコンピューター技術についてぜひ皆さんと議論したいと思っています。メール: qwyaxm@163.net